class TestUnoHumanPlayer(unittest.TestCase): def setUp(self): self.player = HumanUnoPlayer() self.other = HumanUnoPlayer() self.discard = DiscardPile() def test_valid_color_move(self): self.player.hand = [UnoCard(0, 'Number', 'Red')] self.discard.cards = [UnoCard(7, 'Number', 'Red')] self.player.play_card(str(self.player.hand[0]), self.discard) self.assertTrue(self.player.hand_is_empty()) self.assertEqual(str(self.discard.peek()), str(UnoCard(0, 'Number', 'Red'))) def test_valid_number_move(self): self.player.hand = [UnoCard(0, 'Number', 'Red')] self.discard.cards = [UnoCard(0, 'Number', 'Yellow')] self.player.play_card(str(self.player.hand[0]), self.discard) self.assertTrue(self.player.hand_is_empty()) self.assertEqual(str(self.discard.peek()), str(UnoCard(0, 'Number', 'Red'))) def test_valid_wild_move(self): self.player.hand = [UnoCard(-1, 'Wild', 'Black')] self.discard.cards = [UnoCard(0, 'Number', 'Yellow')] self.player.play_card(str(self.player.hand[0]), self.discard) self.assertTrue(self.player.hand_is_empty()) self.assertEqual(str(self.discard.peek()), str(UnoCard(-1, 'Wild', 'Black'))) def test_invalid_move(self): self.player.hand = [UnoCard(0, 'Number', 'Yellow')] self.discard.cards = [UnoCard(7, 'Number', 'Red')] self.player.play_card(str(self.player.hand[0]), self.discard) self.assertEqual(str(self.player.hand[0]), str(UnoCard(0, 'Number', 'Yellow'))) self.assertEqual(str(self.discard.peek()), str(UnoCard(7, 'Number', 'Red')))
class ERSTable(Table): def __init__(self, player_count=2): self.players = [] self.deck = Deck() self.pile = DiscardPile() self.deck.shuffle() for i in range(player_count): self.players.append(ERSPlayer()) self.deal_all() def get_winner(self): for i in range(len(self.players)): return i def play_game(self): player = 0 while not self.winner(): value = 0 if len(self.pile.cards) > 0: value = self.pile.peek().value if value == 1 or value > 10: player = self.war(player) else: if player == 0: raw_input(_("Play a card!")) card = self.players[player].flip() print(_("Player {} plays the {}!").format(player, card)) self.pile.add(card) self.wait_for_slap(0.25) player = ((player + 1) % len(self.players)) print(_("Player {} wins!").format(self.get_winner())) def wait_for_slap(self, t): sleep(t) def war(self, player): value = self.pile.peek().value num = 0 if value == 1: num = 4 else: num = value - 10 for i in range(num): card = self.players[player].flip() print(_("Player {} plays the {}!").format(player, card)) self.pile.add(card) value = card.value self.wait_for_slap(0.25) if value == 1 or value > 10: return player self.players[player].cards = self.pile.cards + self.players[player].hand self.pile.cards = [] return player - 1 def winner(self): for player in self.players: if len(player.hand) == 0: return True return False
class TestDiscardPile(unittest.TestCase): def setUp(self): self.pile = DiscardPile() def test_add_to_discard_pile(self): size = len(self.pile.cards) c = Card(0, "Jokers") self.pile.add(c) self.assertEqual(len(self.pile.cards), size + 1) self.assertEqual(str(self.pile.cards[0]), "Joker") def test_peek(self): self.pile.add(Card(1, "Spades")) self.assertTrue(self.pile.peek().same_as(Card(1, "Spades"))) def test_peek_multiple_cards(self): self.pile.add(Card(1, "Clubs")) self.pile.add(Card(1, "Diamonds")) self.pile.add(Card(1, "Hearts")) self.pile.add(Card(1, "Spades")) self.assertTrue(self.pile.peek().same_as(Card(1, "Spades"))) def test_peek_no_cards(self): self.assertEqual(self.pile.peek(), None) def test_has_double(self): self.pile.add(Card(1, "Clubs")) self.pile.add(Card(1, "Diamonds")) self.assertTrue(self.pile.has_double()) def test_hasnt_double(self): self.pile.add(Card(1, "Clubs")) self.pile.add(Card(2, "Diamonds")) self.assertFalse(self.pile.has_double()) def test_hasnt_double_empty(self): self.assertFalse(self.pile.has_double()) def test_hasnt_double_too_few_cards(self): self.pile.add(Card(6, "Spades")) self.assertFalse(self.pile.has_double()) def test_has_sandwich(self): self.pile.add(Card(1, "Clubs")) self.pile.add(Card(2, "Hearts")) self.pile.add(Card(1, "Diamonds")) self.assertTrue(self.pile.has_sandwich()) def test_hasnt_sandwich(self): self.pile.add(Card(2, "Clubs")) self.pile.add(Card(1, "Hearts")) self.pile.add(Card(1, "Diamonds")) self.assertFalse(self.pile.has_sandwich()) def test_hasnt_sandwich_empty(self): self.assertFalse(self.pile.has_sandwich()) def test_hasnt_sandwich_too_few_cards(self): self.pile.add(Card(1, "Clubs")) self.assertFalse(self.pile.has_sandwich()) self.pile.add(Card(1, "Hearts")) self.assertFalse(self.pile.has_sandwich())
class UnoTable(Table): def __init__(self, player_count = 2): self.players = [] self.deck = UnoDeck() self.deck.shuffle() self.discard = DiscardPile() self.players.append(HumanUnoPlayer('Human 1')) for i in range(player_count - 1): self.players.append(AIUnoPlayer(_('Computer {}').format(i + 1))) self.deal(7) self.current_player = 0 self.TURN_CONS = 1 def get_winner(self): return self.winner() def play_game(self): self.shuffle_and_turn() while not self.winner(): result = None if len(self.deck.cards) == 0: self.shuffle_and_turn() print _("\n~~~~~{}'s Turn~~~~~\n").format(self.players[self.current_player]) if self.players[self.current_player].player_type() == 1: #is AI move = self.players[self.current_player].find_best_move(self.players[(self.current_player + self.TURN_CONS) % (len(self.players))], self.discard) if move == _('Draw'): print _('{} draws a card...').format(self.players[self.current_player]) self.players[self.current_player].draw_from(self.deck) result = _('draw') else: print _('{} plays a {}').format(self.players[self.current_player], move) result = self.players[self.current_player].play_card(move, self.discard) else: #is Human self.print_output_for_human() move = raw_input(_('Please input your move, or draw:\n')) if move.lower().strip() == _('draw'): #draw a card self.players[self.current_player].draw_from(self.deck) print _('You draw a {}').format(self.players[self.current_player].hand[0]) result = _('draw') else: #play a card result = self.players[self.current_player].play_card(move, self.discard) if not result: print _('That is not a valid card/move!\n') else: print _('\n{} plays a {}').format(self.players[self.current_player], move) if result: if len(self.players[self.current_player].hand) == 1: print _('^^^^^ {} says UNO! ^^^^^').format(self.players[self.current_player]) self.determine_next_turn(move) print _('{} wins!').format(self.get_winner()) def winner(self): for i, player in enumerate(self.players): if len(player.hand) == 0: return player #gameplay helper functions def determine_next_turn(self, move): if _('Skip') in move: self.current_player = (self.current_player + 2 * self.TURN_CONS) % (len(self.players)) elif _('Draw Two') in move: self.current_player = (self.current_player + self.TURN_CONS) % (len(self.players)) self.players[self.current_player].draw_from(self.deck) self.players[self.current_player].draw_from(self.deck) elif _('Reverse') in move: self.TURN_CONS *= -1 self.current_player = (self.current_player + self.TURN_CONS) % (len(self.players)) elif _('Wild') in move and self.players[self.current_player].player_type() == 0: valid_color = False while not valid_color: color = raw_input(_('Please input the color for the wild card.\n')) if color in [_('Red'), _('Blue'), _('Green'), _('Yellow')]: valid_color = True self.discard.peek().set_color_of_wild(color) self.current_player = (self.current_player + self.TURN_CONS) % (len(self.players)) else: self.current_player = (self.current_player + self.TURN_CONS) % (len(self.players)) def shuffle_and_turn(self): self.deck.cards.extend(self.discard.cards) self.discard.cards = [] self.deck.shuffle() self.discard.add(self.deck.draw()) def print_hand_count(self): s = '' for p in self.players: s += _('| {} has {} cards in hand.\n').format(p, len(p.hand)) return s.strip() def print_output_for_human(self): print _('+==================================+\n| Cards in deck: {}').format(len(self.deck.cards)) print _('| Top of the discard pile: {}\n|').format(self.discard.peek()) print '{}'.format(self.print_hand_count()) print '+==================================+\n' print _('***Your hand contains***\n{}\n').format(self.players[self.current_player].hand)