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))
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 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))
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)
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)
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)
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)
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))
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))
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))
def test_cards_attr(self): d = Deck(cards=[Card(color=Color.RED, number=2)]) self.assertEqual(len(d._cards), 1)
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)
def test_count_total(self): d = Deck() self.assertEqual(len(d._cards), 108)
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