def get_game_type_and_main_player(game_id: int) -> tuple: """checks redis round_choices entry and finds which player has chosen the highest game and which game is being played. Returns a tuple of (game_type, main_player)""" # get original player order from redis player_order = RedisGetter.round_choices(game_id, 'order') player_order = player_order.split(',') # get choice of each player player1_choice = RedisGetter.round_choices(game_id, f'{player_order[0]}_chosen') player2_choice = RedisGetter.round_choices(game_id, f'{player_order[1]}_chosen') player3_choice = RedisGetter.round_choices(game_id, f'{player_order[2]}_chosen') # if a player's choice is 'pass', it means they are not the main player if player1_choice != 'pass': return player1_choice, player_order[0] elif player2_choice != 'pass': return player2_choice, player_order[1] elif player3_choice != 'pass': return player3_choice, player_order[2] else: # all three players' choice was 'pass' return 'pass', None
def update_player_options(game_id: int): """updates players' options based on current state of choices in redis db""" is_last_choice = RedisGetter.round_choices(game_id, 'last_choice') # get original player order from redis player_order = RedisGetter.round_choices(game_id, 'order') player_order = player_order.split(',') # get current choice of each player player1_choice = RedisGetter.round_choices(game_id, f'{player_order[0]}_chosen') player2_choice = RedisGetter.round_choices(game_id, f'{player_order[1]}_chosen') player3_choice = RedisGetter.round_choices(game_id, f'{player_order[2]}_chosen') # get available games chosen_games = [player1_choice, player2_choice, player3_choice] available_games = get_available_games(chosen_games) player1_options = ['pass'] + available_games if not player1_choice: player1_options = available_games player2_options = ['pass'] + available_games player3_options = ['pass'] + available_games # if all players have made first choice, compare choices and find available ones for each player if player1_choice and player2_choice and player3_choice: # if players 2 and 3 chose a game worth more than what player 1 chose, player 1 can choose again if player1_choice == 'pass' or is_last_choice == 'true': player1_options = ['chosen'] else: player1_options = calculate_player1_options( player1_choice, player2_choice, player3_choice, player1_options) # if player 3 chose a game worth more than what player 2 chose, player 2 can choose again if player2_choice == 'pass' or is_last_choice == 'true': player2_options = ['chosen'] else: player2_options = calculate_player2_options( player2_choice, player3_choice, player2_options) # if player 3 can still choose a game worth more than what they've already chosen, they can choose again if player3_choice == 'pass' or is_last_choice == 'true': player3_options = ['chosen'] if chosen_games.count('pass') == 2: is_last_choice = 'true' # update redis with current options for each player RedisSetter.round_choices(game_id, f'{player_order[0]}_options', ','.join(player1_options)) RedisSetter.round_choices(game_id, f'{player_order[1]}_options', ','.join(player2_options)) RedisSetter.round_choices(game_id, f'{player_order[2]}_options', ','.join(player3_options)) if is_last_choice == 'true': RedisSetter.round_choices(game_id, 'last_choice', is_last_choice)
def create_redis_entry_for_round_choices(game_id: int, players: list, new_game: bool = False): """creates new entry in redis db with empty game choice and assigns players a random order. new_game=True should be set only when a new game (not a new round!) begins so that the order of the players is set (randomly). After that, the same order is kept throughout the game's lifetime (but cycled through) """ if new_game: random.shuffle(players) else: old_order = RedisGetter.round_choices(game_id, 'order') order = old_order.split(',') order.append( order.pop(0) ) # move each player up a spot (the previously first player is now in last spot) players = order for player in players: RedisSetter.round_choices(game_id, f'{player}_chosen', '') RedisSetter.round_choices(game_id, f'{player}_options', 'three,two,one,pass') # player 1 initially shouldn't be able to choose 'pass' if player == players[0]: RedisSetter.round_choices(game_id, f'{player}_options', 'three,two,one') RedisSetter.round_choices(game_id, 'order', ','.join(players)) RedisSetter.round_choices(game_id, 'new_order', ','.join(players)) RedisSetter.round_choices(game_id, 'last_choice', 'false')
def is_round_in_progress(game_id: int) -> bool: """if all players have 'chosen' in their options in redis it means the page was reloaded and the game is in progress.""" players = get_all_players(game_id) for player in players: opt = RedisGetter.round_choices(game_id, f'{player}_options') if opt == 'chosen': return True return False
def get_players_that_need_to_choose_game(game_id: int) -> Union[list, None]: """queries redis db and returns players that can still make a choice of game for round""" if is_round_in_progress(game_id): return None update_player_options(game_id) player_order = RedisGetter.round_choices(game_id, 'new_order') player_order = player_order.split(',') current_player = player_order[0] # remove player from first choosing position if they've already made a choice choice_of_current_player = RedisGetter.round_choices( game_id, f'{current_player}_chosen') if choice_of_current_player: player_order.pop(0) # add player to end of choosing queue if they still have options available options_of_current_player = RedisGetter.round_choices( game_id, f'{current_player}_options') if not options_of_current_player: return None if options_of_current_player != 'chosen': if player_order: if player_order[-1] != current_player: player_order.append(current_player) else: # remove player's _options if player_order is empty RedisSetter.round_choices(game_id, f'{current_player}_options', '') else: # remove player from order if their _choices are chosen if current_player in player_order: player_order.remove(current_player) # save new revised order in redis db RedisSetter.round_choices(game_id, 'new_order', ','.join(player_order)) return player_order
def get_players_choices(game_id: int) -> dict: """returns dictionary containing choices made so far by players""" all_players = get_all_players(game_id) players_choice = {} for player_username in all_players: p_choice = RedisGetter.round_choices(game_id, f'{player_username}_chosen') if not p_choice: p_choice = 'čaka na izbiro' else: p_choice = TRANSLATION_GAME_TYPE[p_choice] players_choice[player_username] = p_choice return players_choice
def update_order_of_players(game_id: str, new_first_player: str = None) -> str: """this method updates the order of players in the :current_round hash in redis. If new_first_player=None, it means that a round is currently in progress (there are cards on the table) and so the first player is simply removed from the order. If new_first_player='some player' it means that the table has been cleared and the first player is known. The other players are determined based on who comes after the known player in the original order found in the :round_choices hash. Returns the player whose turn it is next and updates the whose_turn entry in redis""" original_order = RedisGetter.round_choices(game_id, 'order') original_order = original_order.split(',') if new_first_player is None: order_in_redis = RedisGetter.current_round(game_id, 'order') new_order = order_in_redis.split(',') new_order.pop(0) else: if original_order.index(new_first_player) == 0: new_order = original_order elif original_order.index(new_first_player) == 1: new_order = [ new_first_player, original_order[2], original_order[0] ] elif original_order.index(new_first_player) == 2: new_order = [ new_first_player, original_order[0], original_order[1] ] else: raise RuntimeError( f'Error on trying to retrieve {new_first_player} from {original_order}.' ) RedisSetter.current_round(game_id, 'order', ','.join(new_order)) RedisSetter.current_round(game_id, 'whose_turn', new_order[0]) return new_order[0]
def update_player_choosing(): """handler for sending information of which player can choose again and what choices are available to them""" user = User.query.filter_by(id=session['user_id']).first() game_id = user.current_game player_order = get_players_that_need_to_choose_game(game_id) player_to_choose_game = None player_options = None if player_order: player_to_choose_game = player_order[0] player_options = RedisGetter.round_choices( game_id, f'{player_to_choose_game}_options') co_players_choice = get_players_choices(game_id) data_to_send = { 'player': player_to_choose_game, 'player_options': player_options, 'co_players_choice': co_players_choice } print(f'[SENDING] player to choose: {data_to_send}') socketio.emit('player game options', data_to_send)
def create_redis_entry_for_current_round(game_id: int, dealt_cards: dict, reset: bool = False): """creates new entry in redis db to start a new round. Saves the order of players and the state of the dealt cards. The redis key {game_id}:current_round should be reset once the round is complete (reset=True)""" # save order of players order = RedisGetter.round_choices(game_id, 'order') RedisSetter.current_round(game_id, 'order', order) RedisSetter.current_round(game_id, 'whose_turn', order.split(',')[0]) RedisSetter.current_round(game_id, 'called', '') RedisSetter.current_round(game_id, 'on_table', '') RedisSetter.current_round(game_id, 'main_player_score_pile', '') RedisSetter.current_round(game_id, 'against_players_score_pile', '') # save dealt cards for user, value in dealt_cards.items(): value_for_redis = ','.join(str(card_name) for card_name in value) RedisSetter.current_round(game_id, f'{user}_cards', value_for_redis) RedisSetter.current_round(game_id, f'{user}_played', '') if reset: redis_db.hdel(f'{game_id}:current_round', 'main_player') redis_db.hdel(f'{game_id}:current_round', 'type')
def play(): """handler for main page of game""" update_user_in_game(session['user_id'], True) user = User.query.filter_by(id=session['user_id']).first() game_id = user.current_game co_players = get_co_players(game_id, session['user_id']) all_players = list(co_players.keys()) + [user.username] dealt_cards = get_dealt_cards(game_id, all_players) choose_order = get_players_that_need_to_choose_game(game_id) player_to_choose = None player_to_choose_opts = None if choose_order: player_to_choose = choose_order[0] player_to_choose_opts = RedisGetter.round_choices( game_id, f'{player_to_choose}_options') called = RedisGetter.current_round(game_id, 'called') whose_turn = RedisGetter.current_round(game_id, 'whose_turn') main_player = RedisGetter.current_round(game_id, 'main_player') game_type = RedisGetter.current_round(game_id, 'type') cards_on_table = RedisGetter.current_round(game_id, 'on_table') connect_handler() return render_template('play.html', player=user.username, co_players=co_players, round_state=dealt_cards, player_to_choose=player_to_choose, player_to_choose_opts=player_to_choose_opts, game_id=game_id, called=called, whose_turn=whose_turn, main_player=main_player, game_type=game_type, on_table=cards_on_table)