Beispiel #1
0
 def test_get_card(self):
     d = Deck(cards=[
         Card(color=Color.RED, number=2),
         Card(color=Color.BLUE, number=2),
     ])
     card = d.get_card()
     self.assertEqual(card, Card(color=Color.RED, number=2))
Beispiel #2
0
 def __init__(self, deck=None):
     self.player_list = list()
     self.uid = str(uuid.uuid4())
     self.player_by_uid = dict()
     self.human_players = list()
     if deck is None:
         self.deck = Deck()
     else:
         self.deck = deck
Beispiel #3
0
 def test_get_card_shuffle(self):
     d = Deck(cards=[],
              used_cards=[
                  Card(color=Color.YELLOW, number=2),
                  Card(color=Color.GREEN, number=2),
                  Card(color=Color.BLUE, number=2),
                  Card(color=Color.RED, number=2),
              ])
     active_card = d.active_card
     card = d.get_card()
     self.assertEqual(len(d._cards), 2)
     self.assertEqual(len(d._used_cards), 1)
     self.assertEqual(d.active_card, Card(color=Color.YELLOW, number=2))
Beispiel #4
0
 def test_put_correct_card(self):
     d = Deck(cards=[
         Card(color=Color.RED, number=2),
         Card(color=Color.BLUE, number=2),
         Card(color=Color.BLUE, action=CardAction.SKIP),
         Card(color=Color.BLACK,
              action=CardAction.SET_COLOR,
              required_color=Color.YELLOW),
         Card(color=Color.YELLOW, number=5),
     ])
     while bool(d._cards):
         card = d.get_card()
         d.put_card(card)
Beispiel #5
0
    def test_start_round(self):
        self._get_all_events()
        cards = list()
        for item in range(40):
            cards.append(Card(color=Color.RED, number=1))
        deck = Deck(cards=cards)

        uno_round = UnoRound(deck=deck)
        uno_round.add_player('1')
        uno_round.add_player('2')
        uno_round.start_round()

        self.assertNotEqual(uno_round.current_player_index, None)
        for i in range(2):
            self.assertEqual(len(uno_round.player_list[1].cards), 7)

        self.assertTrue(uno_round.deck.active_card)
        self.assertEqual(len(uno_round.actions_list), 9)
        for item in uno_round.actions_list:
            self.assertTrue(
                item in allowed_actions_for_card(Card(color=Color.RED, number=1))
            )

        events = self._get_all_events()
        logger.debug(events)
        self.assertEqual(len(events), 19)
Beispiel #6
0
 def test_count_by_color(self):
     d = Deck()
     self.assertEqual(len([i for i in d._cards if i.color == Color.RED]),
                      25)
     self.assertEqual(len([i for i in d._cards if i.color == Color.YELLOW]),
                      25)
     self.assertEqual(len([i for i in d._cards if i.color == Color.BLUE]),
                      25)
     self.assertEqual(len([i for i in d._cards if i.color == Color.GREEN]),
                      25)
     self.assertEqual(len([i for i in d._cards if i.color == Color.BLACK]),
                      8)
Beispiel #7
0
 def test_count_by_action(self):
     d = Deck()
     self.assertEqual(
         len([i for i in d._cards if i.action == CardAction.TAKE_TWO]), 8)
     self.assertEqual(
         len([i for i in d._cards if i.action == CardAction.REVERSE]), 8)
     self.assertEqual(
         len([i for i in d._cards if i.action == CardAction.SKIP]), 8)
     self.assertEqual(
         len([i for i in d._cards if i.action == CardAction.SET_COLOR]), 4)
     self.assertEqual(
         len([
             i for i in d._cards
             if i.action == CardAction.TAKE_FOUR_AND_SET_COLOR
         ]), 4)
Beispiel #8
0
    def test_skip_action(self):
        self._get_all_events()
        cards = list()
        for item in range(40):
            cards.append(Card(color=Color.RED, number=1))
        deck = Deck(cards=cards)

        uno_round = UnoRound(deck=deck)
        uno_round.add_player('1')
        uno_round.add_player('2')
        uno_round.start_round()
        uno_round.process_input(
            uno_round.current_player,
            uno_service.UnoService.execute_command.request(Command.TAKE))

        old_current_player_index = uno_round.current_player_index
        player_cards_len = len(uno_round.current_player.cards)
        deck_cards_len = len(uno_round.deck._cards)
        player = uno_round.current_player

        events = self._get_all_events()
        uno_round.process_input(
            uno_round.current_player,
            uno_service.UnoService.execute_command.request(Command.SKIP))
        # current player changed
        self.assertNotEqual(uno_round.current_player_index,
                            old_current_player_index)

        # card not removed from player
        self.assertEqual(player_cards_len, len(player.cards))

        # card not taken from deck
        self.assertEqual(deck_cards_len, len(uno_round.deck._cards))

        # proper actions setted
        self.assertEqual(len(uno_round.actions_list), 8)
        for item in uno_round.actions_list:
            self.assertTrue(item in allowed_actions_for_card(
                Card(color=Color.RED, number=1)))
        # player put card events
        events = self._get_all_events()
        self.assertEqual(len(events), 3)
        # your turn event
        self.assertTrue(
            self._find_event(NotificationType.PLAYER_SKIPPED, events))
        self.assertTrue(self._find_event(NotificationType.YOUR_TURN, events))
Beispiel #9
0
    def test_take_action(self):
        self._get_all_events()
        cards = list()
        for item in range(40):
            cards.append(Card(color=Color.RED, number=1))
        deck = Deck(cards=cards)

        uno_round = UnoRound(deck=deck)
        uno_round.add_player('1')
        uno_round.add_player('2')
        uno_round.start_round()
        events = self._get_all_events()

        old_current_player_index = uno_round.current_player_index
        player_cards_len = len(uno_round.current_player.cards)
        deck_cards_len = len(uno_round.deck._cards)
        player = uno_round.current_player
        events = self._get_all_events()

        uno_round.process_input(
            player,
            uno_service.UnoService.execute_command.request(Command.TAKE))

        # current player equal
        self.assertEqual(uno_round.current_player_index,
                         old_current_player_index)

        # card added to player cards
        self.assertEqual(player_cards_len + 1, len(player.cards))

        # card removed from deck
        self.assertEqual(deck_cards_len - 1, len(uno_round.deck._cards))

        # proper actions setted
        self.assertEqual(len(uno_round.actions_list), 3)
        for item in uno_round.actions_list:
            self.assertTrue(
                item in [PutTakenCardAction, SkipAction, ListCardsAction])

        events = self._get_all_events()
        self.assertEqual(len(events), 2)
        self.assertTrue(
            self._find_event(NotificationType.YOU_TOOK_CARD, events))
        self.assertTrue(
            self._find_event(NotificationType.PLAYER_TOOK_CARD, events))
Beispiel #10
0
    def test_take_two_and_skip_action(self):
        self._get_all_events()
        cards = list()
        for item in range(40):
            cards.append(Card(color=Color.RED, number=1))
        deck = Deck(cards=cards)

        uno_round = UnoRound(deck=deck)
        uno_round.add_player('1')
        uno_round.add_player('2')
        uno_round.start_round()
        events = self._get_all_events()

        uno_round.current_player.cards.append(
            Card(color=Color.RED, action=CardAction.TAKE_TWO))

        uno_round.process_input(
            uno_round.current_player,
            uno_service.UnoService.execute_command.request(
                Command.PUT, Card(color=Color.RED,
                                  action=CardAction.TAKE_TWO)))

        with self.assertRaises(ActionNotAllowedError):
            uno_round.process_input(
                uno_round.current_player,
                uno_service.UnoService.execute_command.request(
                    Command.PUT, Card(color=Color.RED, number=1)))

        old_current_player_index = uno_round.current_player_index
        player_cards_len = len(uno_round.current_player.cards)
        deck_cards_len = len(uno_round.deck._cards)
        player = uno_round.current_player
        events = self._get_all_events()

        uno_round.process_input(
            uno_round.current_player,
            uno_service.UnoService.execute_command.request(
                Command.TAKE_TWO_AND_SKIP))

        # current player changed
        self.assertNotEqual(uno_round.current_player_index,
                            old_current_player_index)

        # cards added to player
        self.assertEqual(player_cards_len + 2, len(player.cards))

        # card removed from deck
        self.assertEqual(deck_cards_len - 2, len(uno_round.deck._cards))

        # proper actions setted
        self.assertEqual(len(uno_round.actions_list), 8)
        for item in uno_round.actions_list:
            self.assertTrue(item in allowed_actions_for_card(
                Card(color=Color.RED, number=1)))
        # player put card events
        events = self._get_all_events()
        self.assertEqual(len(events), 4)
        # your turn event
        self.assertTrue(self._find_event(NotificationType.YOUR_TURN, events))
        self.assertTrue(
            self._find_event(NotificationType.YOU_TOOK_CARD, events))
        self.assertTrue(
            self._find_event(NotificationType.PLAYER_TOOK_CARDS, events))
Beispiel #11
0
 def test_cards_attr(self):
     d = Deck(cards=[Card(color=Color.RED, number=2)])
     self.assertEqual(len(d._cards), 1)
Beispiel #12
0
 def test_count_by_class(self):
     d = Deck()
     self.assertEqual(len([i for i in d._cards if i.action is None]),
                      108 - 32)
     self.assertEqual(len([i for i in d._cards if i.action is not None]),
                      32)
Beispiel #13
0
 def test_count_total(self):
     d = Deck()
     self.assertEqual(len(d._cards), 108)
Beispiel #14
0
class UnoRound(object):

    uid = None
    direction = LEFT
    deck = None
    player_list = None
    current_player_index = None
    actions_list = None
    player_by_uid = None
    taken_card = None
    human_players = None

    def __init__(self, deck=None):
        self.player_list = list()
        self.uid = str(uuid.uuid4())
        self.player_by_uid = dict()
        self.human_players = list()
        if deck is None:
            self.deck = Deck()
        else:
            self.deck = deck

    def get_player(self, player_uid):
        return self.player_by_uid[player_uid]

    def add_player(self, player_uid, player_type=None):
        if player_type == 'human':
            self.human_players.append(player_uid)
        if len(self.player_list) < MAX_PLAYERS:
            player = Player(player_uid)
            self.player_list.append(player)
            self.player_by_uid[player_uid] = player
            return player
        else:
            raise MaxPlayersReachedException('Max players reached')

    def set_dealer(self):
        self.current_player_index = random.randint(0, len(self.player_list)-1)

    def deal_cards(self, deck, player_list):
        CARDS_TO_DEAL = 7
        for item in range(CARDS_TO_DEAL):
            for player in player_list:
                card = deck.get_card()
                player.add_card(card)

    def get_allowed_actions(self):
        return set([item.command_id for item in self.actions_list])

    def set_first_card(self):
        card = self.deck.get_card()
        while card.action is not None:
            self.deck._cards.append(card)
            card = self.deck.get_card()
        self.deck.put_card(card)
        self.actions_list = allowed_actions_for_card(card)

    def notify_all(self, **kwargs):
        for player in self.player_list:
            player.notify_user(**kwargs)

    def notify_all_except_current(self, **kwargs):
        for player in self.player_list:
            if player != self.current_player:
                player.notify_user(**kwargs)

    def start_round(self):
        self.deal_cards(self.deck, self.player_list)
        self.set_dealer()
        self.set_first_card()

        self.notify_all(code=NotificationType.ACTIVE_CARD, card=self.deck.active_card)
        self.notify_all(code=NotificationType.ROUND_STARTED, round_uid=self.uid)
        self.current_player.notify_user(
            code=NotificationType.YOUR_TURN,
            allowed_actions=self.get_allowed_actions()
        )
        logger.debug('round started')

    @property
    def current_player(self):
        return self.player_list[self.current_player_index]

    def get_score(self):
        total = 0
        for player in self.player_list:
            for card in player.cards:
                total += card.cost
        return total

    def change_direction(self):
        if self.direction == RIGHT:
            self.direction = LEFT
        else:
            self.direction = RIGHT

    def remove_player(self, player_uid):
        player = self.player_by_uid[player_uid]
        current_player = self.current_player
        if player_uid == self.current_player.uid:
            if len(self.human_players) > 0:
                self.set_next_player()
                self.current_player.notify_user(
                    code=NotificationType.YOUR_TURN,
                    allowed_actions=self.get_allowed_actions()
                )
        self.current_player_index = self.player_list.index(current_player)
        self.human_players.remove(player_uid)
        self.player_by_uid.pop(player_uid)
        self.player_list.remove(player)
        self.notify_all(code=NotificationType.PLAYER_DISCONNECTED)
        self.check_for_win()

    def set_next_player(self):
        if self.direction == 1 and self.current_player_index + 1 >= len(self.player_list):
            self.current_player_index = 0
        elif self.direction == -1 and self.current_player_index - 1 < 0:
            self.current_player_index = len(self.player_list) - 1
        else:
            self.current_player_index += self.direction

    def process_input(self, player, command_request):
        if player != self.current_player:
            raise NotYourTurnException('not your turn')

        # TODO: check player has card

        action_processed = False
        for action in self.actions_list:
            if action.check_condition(command_request, self):
                action.update_round(command_request, self)
                action_processed = True
                break

        if not action_processed:
            raise ActionNotAllowedError('action_not_allowed')
        else:
            self.check_for_win()

    async def process_event(self, event):
        if event['channel'] == 'game_command':
            if event['player_uid'] in self.player_by_uid.keys():
                if event.get('command') == Command.DISCONNECT:
                    self.remove_player(event['player_uid'])
                    return True
                try:
                    self.process_input(
                        self.get_player(event['player_uid']), event['command']
                    )
                except NotYourTurnException:
                    self.get_player(event['player_uid']).notify_user(
                        exception=True,
                        not_your_turn=uno_service.NotYourTurn()
                    )
                except ActionNotAllowedError:
                    self.get_player(event['player_uid']).notify_user(
                        exception=True,
                        not_allowed=uno_service.ActionNotAllowed(
                            'allowed actions : {}'.format(
                                set(
                                    [Command.name_of(item.command_id) for item in self.actions_list]
                                )
                            )
                        )
                    )

    def check_for_win(self):
        if len(self.human_players) == 0:
            event_manager.add_event(
                {'channel': 'game_queue', 'code': 'finish_game', 'uno_round': self}
            )
            return True
        if len(self.human_players) == 1 and len(self.player_list) == 1:
            self.notify_all(
                code=NotificationType.ROUND_FINISHED, winner=self.player_list[0].uid,
                uno_round=self
            )
            event_manager.add_event(
                {'channel': 'game_queue', 'code': 'finish_game', 'uno_round': self}
            )
        for player in self.player_list:
            if not player.cards:
                self.notify_all(
                    code=NotificationType.ROUND_FINISHED, winner=player.uid,
                    uno_round=self
                )
                event_manager.add_event(
                    {'channel': 'game_queue', 'code': 'finish_game', 'uno_round': self}
                )
                return True
        return False