def test_game_has_ended_when_player_reached_points_to_win(default_game_with_3_players): sess: GameStateMachine = default_game_with_3_players sess.start_game() assert sess.state == GameStates.PLAYERS_SUBMITTING_CARDS normal_players = [ p for p in sess.players if p.current_role == CardsAgainstHumanityRoles.PLAYER ] active_card_picks = sess.currently_active_card.pick for player in normal_players: sess.player_submit_card( PlayerSubmitCards( submitting_user=player.username, cards=player.cards_in_hand[0:active_card_picks], ) ) assert sess.state == GameStates.TZAR_CHOOSING_WINNER normal_players[0].points = POINTS_TO_WIN - 1 # Making the next point trigger win. the_winner_player: CardsAgainstHumanityPlayer = normal_players[0] winning_submission = the_winner_player.submissions[-1] with pytest.raises(GameHasEnded): sess.select_winner( sender_name=sess.tzar.username, winner=SelectWinningSubmission(submission=winning_submission), )
def test_logical_error_when_selected_winner_submission_does_not_exist( default_game_with_3_players, ): sess: GameStateMachine = default_game_with_3_players sess.start_game() assert sess.state == GameStates.PLAYERS_SUBMITTING_CARDS normal_players = [ p for p in sess.players if p.current_role == CardsAgainstHumanityRoles.PLAYER ] active_card_picks = sess.currently_active_card.pick for player in normal_players: sess.player_submit_card( PlayerSubmitCards( submitting_user=player.username, cards=player.cards_in_hand[0:active_card_picks], ) ) with pytest.raises(InvalidPlayerAction): sess.select_winner( sender_name=sess.tzar.username, winner=SelectWinningSubmission( submission=Submission( black_card=sess.currently_active_card, white_cards=sess.white_cards[0 : sess.currently_active_card.pick], ) ), )
def test_game_has_ended_when_ran_out_of_white_cards(default_game_with_3_players): sess: GameStateMachine = default_game_with_3_players sess.start_game() assert sess.state == GameStates.PLAYERS_SUBMITTING_CARDS sess.white_cards = [ sess.white_cards[-1] ] # Manually removing leftover white cards from session normal_players = [ p for p in sess.players if p.current_role == CardsAgainstHumanityRoles.PLAYER ] active_card_picks = sess.currently_active_card.pick for player in normal_players: sess.player_submit_card( PlayerSubmitCards( submitting_user=player.username, cards=player.cards_in_hand[0:active_card_picks], ) ) assert sess.state == GameStates.TZAR_CHOOSING_WINNER the_winner_player: CardsAgainstHumanityPlayer = normal_players[0] winning_submission = the_winner_player.submissions[-1] sess.select_winner( sender_name=sess.tzar.username, winner=SelectWinningSubmission(submission=winning_submission), ) with pytest.raises(GameHasEnded): sess.advance_after_voting()
def test_invalid_player_action_when_player_tries_to_submit_cards( default_game_with_3_players, ): sess: GameStateMachine = default_game_with_3_players with pytest.raises(InvalidPlayerAction): sess.player_submit_card( PlayerSubmitCards( submitting_user=sess.players[0].username, cards=sess.players[0].cards_in_hand[0:1], ) )
def test_player_select_winner_behaviour(database_connection, prefill_official_cards_to_database): """ room_name: str, round_count: int, db: Session, preferences: GamePreferences, :return: """ prefill_official_cards_to_database() sm = GameFactory.new_session( room_name="test room", db=database_connection, preferences=GamePreferences.god_is_dead_mode(), ) assert isinstance(sm, GodIsDeadModeStateMachine) players = ["P1", "P2", "P3"] for p in players: sm.player_join(p) assert len(sm.players) == 3 assert sm.tzar() is None sm.start_game() with pytest.raises(GameHasEnded): for i in range(15): to_pick = sm.currently_active_card.pick submissions = {} for p in players: cards_to_submit = sm.player_lookup[p].cards_in_hand[0:to_pick] submissions[p] = cards_to_submit sm.player_submit_card( PlayerSubmitCards(submitting_user=p, cards=cards_to_submit)) for p in players: sub = Submission( black_card=sm.currently_active_card, white_cards=submissions[list(submissions.keys())[0]], ) sws = SelectWinningSubmission(submission=sub) sm.select_winner( sender_name=p, winner=sws, ) sm.advance_after_voting() assert sm.player_lookup[players[0]].points == i + 1 assert sm.player_lookup[players[0]].points == 10 assert sm.player_lookup[players[1]].points == 0 assert sm.player_lookup[players[2]].points == 0
def test_player_advance_after_winner_raises_exception_when_submitted_invalidly( database_connection, prefill_official_cards_to_database): """ room_name: str, round_count: int, db: Session, preferences: GamePreferences, :return: """ prefill_official_cards_to_database() sm = GameFactory.new_session( room_name="test room", db=database_connection, preferences=GamePreferences.god_is_dead_mode(), ) assert isinstance(sm, GodIsDeadModeStateMachine) players = ["P1", "P2", "P3"] for p in players: sm.player_join(p) assert len(sm.players) == 3 assert sm.tzar() is None sm.start_game() to_pick = sm.currently_active_card.pick submissions = {} for p in players: cards_to_submit = sm.player_lookup[p].cards_in_hand[0:to_pick] submissions[p] = cards_to_submit sm.player_submit_card( PlayerSubmitCards(submitting_user=p, cards=cards_to_submit)) for p in players: sub = Submission( black_card=sm.currently_active_card, white_cards=submissions[list(submissions.keys())[0]], ) sws = SelectWinningSubmission(submission=sub) sm.select_winner( sender_name=p, winner=sws, ) # Only the last advance is valid if p != players[-1]: with pytest.raises(InvalidPlayerAction): print(f"{p} votes") sm.advance_after_voting() else: sm.advance_after_voting()
def test_logical_error_when_non_existing_palyer_submits(default_game_with_3_players): sess: GameStateMachine = default_game_with_3_players sess.start_game() assert sess.state == GameStates.PLAYERS_SUBMITTING_CARDS expected_card_count = sess.currently_active_card.pick with pytest.raises(LogicalError): sess.player_submit_card( PlayerSubmitCards( submitting_user="******", cards=sess.players[0].cards_in_hand[0:expected_card_count], ) )
def __init__( self, room_name, db: Session, preferences: GamePreferences, ): self.session = GameFactory.new_session(room_name, db=db, preferences=preferences) self.event_mapping: Dict[Any, Reaction] = { PlayerSubmitCards.event_id(): Reaction(event_callback=self.session.player_submit_card), SelectWinningSubmission.event_id(): Reaction(event_callback=self.session.select_winner, ), }
def test_invalid_player_action_when_player_tries_to_submit_cards_wrong_number( default_game_with_3_players, ): sess: GameStateMachine = default_game_with_3_players sess.start_game() assert sess.state == GameStates.PLAYERS_SUBMITTING_CARDS expected_card_count = sess.currently_active_card.pick with pytest.raises(InvalidPlayerAction): sess.player_submit_card( PlayerSubmitCards( submitting_user=sess.players[0].username, cards=sess.players[0].cards_in_hand[0 : expected_card_count + 1], ) )
def test_invalid_player_action_when_submitting_not_owned_cards( default_game_with_3_players, ): sess: GameStateMachine = default_game_with_3_players sess.start_game() assert sess.state == GameStates.PLAYERS_SUBMITTING_CARDS normal_players = [ p for p in sess.players if p.current_role == CardsAgainstHumanityRoles.PLAYER ] active_card_picks = sess.currently_active_card.pick for player in normal_players: with pytest.raises(InvalidPlayerAction): sess.player_submit_card( PlayerSubmitCards( submitting_user=player.username, cards=sess.white_cards[0:active_card_picks], ) # <- Cheeky stuff in this line, # this should come from the player )
async def submit_cards( room_name: str, cards: List[WhiteCard], game_mapper: GameEventMapper = Depends(get_game_mapper), token: str = Depends(JWTBearer()), conman: ConnectionManager = Depends(get_websocket_connection_manager), ): user = decodeJWT(token) if user is None: raise HTTPException(404, "User not found with this token.") room = game_mapper.get_game(room_name) if room is None: raise HTTPException(404, "Room does not exist.") room.on_new_event( PlayerSubmitCards(submitting_user=user.user_id, cards=cards), user.user_id, ) await broadcast_event(room_name, conman, f"{user.user_id} has submitted cards!") return GameStatePlayerView.from_game_state(room.session, user.user_id)
def test_game_starts_only_with_enough_players( database_connection, prefill_cards_to_database ): prefill_cards_to_database() db = database_connection sess: GameStateMachine = GameFactory.new_session( "test", db, GamePreferences.default() ) ### STARTING GAME PHASE ###### with pytest.raises(InvalidPlayerAction): sess.start_game() assert sess.state == GameStates.STARTING sess.player_join("Joe") sess.player_join("David") sess.player_join("Peter") sess.start_game() assert sess.state == GameStates.PLAYERS_SUBMITTING_CARDS assert sess.currently_active_card.pick is not None ### TZAR ELECTION ### tzars = [ p for p in sess.players if p.current_role == CardsAgainstHumanityRoles.TZAR ] assert len(tzars) == 1 first_tzar = tzars[0] everyone_else: List[CardsAgainstHumanityPlayer] = [ p for p in sess.players if p.current_role == CardsAgainstHumanityRoles.PLAYER ] ### ASSERTING PLAYER CARD ASSIGNMENT ### active_card_picks = sess.currently_active_card.pick for player in everyone_else: assert len(player.cards_in_hand) == CARDS_IN_PLAYER_HAND sess.player_submit_card( PlayerSubmitCards( submitting_user=player.username, cards=player.cards_in_hand[0:active_card_picks], ) ) assert len(player.cards_in_hand) == CARDS_IN_PLAYER_HAND - active_card_picks ### TZAR IS CHOSING THE WINNER ### assert sess.state == GameStates.TZAR_CHOOSING_WINNER the_winner_player: CardsAgainstHumanityPlayer = everyone_else[0] winning_submission = the_winner_player.submissions[-1] sess.select_winner( sender_name=sess.tzar.username, winner=SelectWinningSubmission(submission=winning_submission), ) ### CHECK AWARDED POINTS ### for p in everyone_else: if p != the_winner_player: assert p.points == 0 else: assert p.points == 1 sess.advance_after_voting() new_tzars = [ p for p in sess.players if p.current_role == CardsAgainstHumanityRoles.TZAR ] assert len(new_tzars) == 1, "must be only 1 tzar!" assert ( new_tzars[0] != first_tzar ), "The same player cannot be tzar two times in a row"