def is_valid_action(user_id, action, game_state, target_name=None):
    """Determine if the provided in-game player action should be executed or not.

    In-game player actions:
      `vote`
      `night_kill(wolf night aciton)`
      `peek(seer night action)`
      `save(angel night action)`
    """
    user_map = UserMap()

    if not target_name:
        return False, RESPONSE['need_target']

    if user_map:
        target_id = user_map.get(name=target_name)
        user_name = user_map.get(user_id)

        if not target_id and target_name != 'pass':
            return False, RESPONSE['user_n_in_game']

    player_action_fn = PLAYER_ACTION_MAPPING.get(action, None)
    if player_action_fn:
        return player_action_fn(user_id, action, game_state, target_name)

    return False, RESPONSE['invalid']
def vote(user_id, action, game_state, target_name):
    user_map = UserMap()
    target_id = user_map.get(name=target_name)
    user_name = user_map.get(user_id)

    if not status.player_in_game(game_state, user_id):
        return False, RESPONSE['u_not_in_game']

    if not status.is_player_alive(game_state, user_id):
        return False, RESPONSE['u_not_alive']

    if status.get_current_round(game_state) != 'day':
        return False, RESPONSE['not_day']

    if target_name == 'pass':
        return True, user_name + RESPONSE['pass']

    if not status.player_in_game(game_state, target_id):
        return False, RESPONSE['t_not_in_game']

    if not status.is_player_alive(game_state, target_id):
        return False, RESPONSE['t_not_alive']

    if status.has_voted(game_state, user_id):
        return True, user_name + ' changed vote to ' + '*' + target_name + '*'

    return True, user_name + ' voted for ' + '*' + target_name + '*'
def peek(user_id, action, game_state, target_name):
    user_map = UserMap()
    role_map = {
        's': "the Seer",
        'w': "a wolf",
        'v': "a vanilla villa",
        'a': "the Angel"
    }

    target_id = user_map.get(name=target_name)

    user_name = user_map.get(user_id)

    if not status.player_in_game(game_state, user_id):
        return False, RESPONSE['noop']

    if not status.is_player_alive(game_state, user_id):
        return False, RESPONSE['dead_villa']

    #if status.get_current_round(game_state) != 'night':
    #    return False, RESPONSE['noop']

    if status.player_role(game_state, user_id) != 's':
        return False, RESPONSE['not_seer']

    target_role = status.player_role(game_state, target_id)
    target_str = RESPONSE['peek']

    return True, target_name + "'s role is " + role_map[target_role]
def night_kill(game_state, user_id, *args):
    """Night kill the selected player."""
    arg_list = args[0]

    print arg_list
    print len(arg_list)

    if len(arg_list) < 1:
        return "Have to pick a target.", None

    elif len(arg_list) > 2:
        return "Not a valid command.", None

    else:
        user_map = UserMap()

        target_name = arg_list[1]
        target_id =  user_map.get(name=target_name)
        result, message = is_valid_action(user_id, 'night_kill', game_state, target_name=target_name)

        if not result:
            return message, None

        else:
            new_game = update_game_state(game_state, 'player_status', player=target_id, status='dead')
            eaten_str = "%s was night killed." % (target_name)

            return resolve_night_round(new_game, alert=eaten_str), None
def list_votes(g, *args):
    """
    Print a list of all the people alive.

    votes is a dictionary with-
    key: voter_id
    value: voted_on_id

    """
    votes = get_all_votes(g)
    out_list = []
    if votes:
        u = UserMap()
        # turn id's into names
        # voter ' voted ' votee
        for v_id in votes.keys():
            voter_name = u.get(user_id=v_id)
            votee_name = u.get(user_id=votes[v_id])
            if votee_name:
                tmp = voter_name + ' voted ' + votee_name
            else:
                tmp = voter_name + ' passed.'
            out_list.append(tmp)

        return '\n'.join(out_list), None

    return 'Cannot list votes now.', None
def eat_player(g, user_id, *args):
    """
    ex. *args = (['kill', 'maksym'], )
    arg_list =
    target_name = args[1]

    user_name = u.id_dict.get(user_id)

    """
    arg_list = args[0]

    if len(arg_list) < 1: # no target no good
        return "Have to pick a target.", None
    elif len(arg_list) > 2: # too many args
        return "Not a valid command.", None
    else:
        u = UserMap() # get usermap

        target_name = arg_list[1]
        target_id =  u.get(name=target_name) # turn name into id
        result, message = is_valid_action(user_id, 'kill', g, target_name=target_name)
        if not result:
            # was not a valid kill
            return message, None
        else:
            # player is eaten
            # update state
            # changes targeted player's status to dead
            new_g = update_game_state(g, 'player_status', player=target_id, status='dead')
            # tell the players.
            eaten_str = "%s was eaten." % (target_name)
            return resolve_night_round(new_g, alert=eaten_str), None
def message_everyone_roles(g):
    """
    for every player in game.
    DM them their roles.

    """
    u = UserMap()
    # player_role(g, player_id)

    all_alive = [(u.get(user_id=p_id, DM=True), player_role(g, p_id))
                for p_id in players_in_game(g)
                    if is_player_alive(g, p_id)]

    print(all_alive)

    for im, role in all_alive:
        if role=='v':
            nice=" Plain Villager"
        elif role=='w':
            nice=" Werewolf. *Awoooo!*"
        elif role=='s':
            nice=" Seer."
        elif role=='b':
            nice=" Bodyguard."
        send_message(nice, channel=im)
def join(g, user_id, *args):
    """
    See if player is allowed to join.
    If so let add them to the game.

    """
    result, message = mod_valid_action(user_id, 'join', g)

    if not result:
        return message, None # could not join

    # if player successfully joins.
    u = UserMap()

    user_name = u.get(user_id=user_id)

    if not user_name:
        # user not in user_map yet
        # get_user_name polls slack and adds to user map
        user_name = get_user_name(user_id)

    # update state with new player
    mutated_g = update_game_state(g, 'join', player=user_id)

    # tell the channel the player joined.
    join_message = "%s joined the game." % user_name
    return join_message, None
def list_players(g, user_id, *args):
    """

    * args is args to command list
    g -> string to Slack of players
      -> "\n".join([list of players])

      "player_name"|"status"

    """
    u = UserMap()

    # gets all names.
    return '\n'.join([u.get(user_id=p_id) + ' | ' + player_status(g, p_id)
                    for p_id in players_in_game(g)]), None
def join(game_state, user_id, *args):
    """Join the game if the player hasn't joined yet."""
    result, message = mod_valid_action(user_id, 'join', game_state)

    if not result:
        return message, None

    user_map = UserMap()
    user_name = user_map.get(user_id=user_id)

    if not user_name:
        user_name = get_user_name(user_id)

    new_game_w_new_player = update_game_state(game_state, 'join', player=user_id)

    join_message = "%s joined the game." % user_name
    return join_message, None
def player_vote(game_state, user_id, *args):
    """Update the game_state with a players lynch vote."""
    user_map = UserMap()
    arg_list = args[0]

    if len(arg_list) < 1:
        return "Have to vote FOR someone.", None

    elif len(arg_list) > 2:
        return "Not a valid command.", None

    else:
        target_name = arg_list[1]
        target_id =  user_map.get(name=target_name)

        result, message = is_valid_action(user_id, 'vote', game_state, target_name=target_name)
        if not result:
            return message, None

        else:
            new_game = update_game_state(game_state, 'vote', voter=user_id, votee=target_id)

            if status.did_everyone_vote(new_game):
                result_id = resolve_votes(new_game)

                if result_id:
                    result_name = user_map.get(user_id=result_id)

                    set_deaths_in_game_state = update_game_state(new_game, 'player_status', player=result_id, status='dead')
                    reset_game_votes = update_game_state(set_deaths_in_game_state, 'reset_votes')

                    lynch_str = "%s was lynched." % (result_name)
                    return resolve_day_round(set_deaths_in_game_state, alert=lynch_str), None

                else:
                    return resolve_day_round(new_game, alert='*No one dies.*'), None

            else:
                return list_votes(new_game)[0] + '\n\n' + message, None

            return message, None
def list_votes(game_state, *kwargs):
    """List all votes from players int he game."""
    votes = status.get_all_votes(game_state)

    out_list = []
    if votes:
        user_map = UserMap()
        for voter_id in votes.keys():
            voter_name = user_map.get(user_id=voter_id)
            votee_name = user_map.get(user_id=votes[voter_id])

            if votee_name:
                vote_mess = voter_name + ' voted ' + votee_name
            else:
                vote_mess = voter_name + ' passed'

            out_list.append(vote_mess)

        return '\n'.join(out_list), None

    return 'Cannot list votes now', None
def start_countdown(game_state, user_id, *kwargs):
    """Start a countdown when it's day time in order to push inactive players to vote.
    We'll send them an annoyance ping and then `pass` their vote if they don't vote. 
    """
    import threading
    user_map = UserMap()

    def check():
        check_game = get_game_state()

        result, message = mod_valid_action(user_id, 'countdown', check_game)
        if not result:
            return False, message

        all_alive = status.get_all_alive(game_state)
        yet_to_vote_list = [player_id for player_id in all_alive if not status.has_voted(game_state, player_id)]
        if len(yet_to_vote_list) > 1:
            return False, 'Countdown cannot start now.'

        yet_to_vote = yet_to_vote_list[0]
        return True, yet_to_vote

    def callback_vote():
        check_bool, yet_to_vote = check()
        if check_bool:
            check_game = get_game_state()
            send_message(player_vote(check_game, yet_to_vote, ['vote', 'pass'])[0])

    check_bool, message = check()
    if not check_bool:
        return message, None

    message_str = 'Countdown started. 60 seconds left.\n ' + user_map.get(user_id=message) + ' please vote. Or your vote will be passed.'

    t = threading.Timer(60.0, callback_vote)
    t.start()

    return message_str, None
def seer_peek_player(game_state, user_id, *args):
    """Seer can peek a players role during the night."""
    user_map = UserMap()
    arg_list = args[0]

    if len(arg_list) < 1:
        return "Have to pick a target.", None

    elif len(arg_list) > 2:
        return "Not a valid command.", None

    else:
        target_name = arg_list[1]
        target_id = user_map.get(name=target_name)
        result, message = is_valid_action(user_id, 'peek', game_state, target_name=target_name)

        if not result:
            return message, None

        else:
            player_channel = user_map.get(user_id=user_id, DM=True)
            send_message(message, channel=player_channel)

            return "", None
def night_kill(user_id, action, game_state, target_name):
    user_map = UserMap()
    target_id = user_map.get(name=target_name)
    user_name = user_map.get(user_id)

    if not status.player_in_game(game_state, user_id):
        return False, RESPONSE['noop']

    #if status.player_role(game_state, user_id) != 'w':
    #    return False, RESPONSE['noop']

    if not status.is_player_alive(game_state, user_id):
        return False, 'Dead wolves can not kill.'

    #if status.get_current_round(game_state) != 'night':
    #    return False, RESPONSE['noop']

    if not status.player_in_game(game_state, target_id):
        return False, RESPONSE['noop']

    if not status.is_player_alive(game_state, target_id):
        return False, RESPONSE['noop']

    return True, ""
def message_everyone_roles(game_state):
    """Ping players with their roles."""
    user_map = UserMap()

    role_message_mapping = {
        'v': " Vanilla Villa\nhttps://media.giphy.com/media/26ufgQWWT3BUtSRq0/giphy.gif",
        'w': " Werewolf\nhttps://media.giphy.com/media/VTGEse4Pt422I/giphy.gif",
        's': " Seer\nhttps://media.giphy.com/media/bpIWfYfOiHR3G/giphy.gif",
        'a': " Angel\nhttps://media.giphy.com/media/xbbq3NUIOtTVu/giphy.gif"
    }

    def _player_tuple(player_id, game_state):

        return (user_map.get(user_id=player_id, DM=True), status.player_role(game_state, player_id))

    all_alive = [_player_tuple(player_id, game_state) for player_id in status.players_in_game(game_state) if status.is_player_alive(game_state, player_id)]

    for im, role in all_alive:
        dm_message = role_message_mapping[role]
        send_message(dm_message, channel=im)
def make_end_round_str(game_state, alert=None, game_over=None):
    """Reconcile end of day actions and either enter night mode or end game."""
    user_map = UserMap()

    round_end_str = ''

    if alert:
        round_end_str += alert

    if game_over:
        if game_over == 'w':
            round_end_str += "\n Game Over. Werewolves wins.\n"

        elif game_over == 'v':
            round_end_str += "\n Game Over. Village wins.\n"

        def player_role_string(player_id, game_state):
            return user_map.get(user_id=player_id) + "%s | %s" % (user_map.get(user_id=player_id), status.player_role(game_state, player_id))

        status.player_roles = [player_role_string(player_id, game_state) for player_id in status.players_in_game(game_state)]
        round_end_str += '\n'.join(status.player_roles)

    return round_end_str
Пример #18
0
def is_valid_action(user_id, action, g, target_name=None):
    """
    For game actions only.
    - vote
    - eat(kill)
    - TODO: seer
    - TODO: bodyguard
    user_id, action, game state
    -> (True/False, message)
    """
    # DRY yo, cleaner response messages.
    MSG = {
        'u_not_in_game':'You are not in the game',
        'u_not_alive': 'You are not alive.',
        't_not_alive': 'Target is not alive.',
        't_not_in_game': 'Target is not in game.',
        'not_wolf': 'You are not a werewolf.',
        'not_night': 'It is not night.',
        'not_day': 'It is not day.',
        'has_voted': 'You have already voted.'
    }

    def vote():
        # 1) Make sure player who made the command
        # is in the game
        if not player_in_game(g, user_id):
            return False, MSG['u_not_in_game']
        # is alive
        if not is_player_alive(g, user_id):
            return False, MSG['u_not_alive']
        # only valid during day
        if get_current_round(g) != 'day':
            return False, MSG['not_day']

        # if target_name=pass is okay
        if target_name == 'pass':
            return True, user_name + ' wants to pass.'

        # target is in game
        if not player_in_game(g, target_id):
            return False, MSG['t_not_in_game']
        # target is alive
        if not is_player_alive(g, target_id):
            return False, MSG['t_not_alive']

        # voting again just changes your vote.
        if has_voted(g, user_id):
            return True, user_name + ' changed vote to ' + '*'+target_name + '.*'

        # after each success vote should list all votes.
        return True, user_name + ' voted for ' + '*' + target_name + '.*'

    def kill():
        # 1) Make sure player who made the command
        # is in the game
        if not player_in_game(g,user_id):
            return False, 'Not allowed.'
        # 1a) is a werewolf
        # Only werewolf can use kill. (for now)
        if player_role(g, user_id) != 'w':
            return False, 'Not allowed.'
        # 1c) is alive
        if not is_player_alive(g, user_id):
            return False, 'Dead wolves can not kill.'
        # 2) Kill command only valid at night.
        if get_current_round(g) != 'night':
            return False, 'Not allowed.'
        # 3) Target must be in game.
        if not player_in_game(g, target_id):
            return False, 'Not allowed.'
        # 4) Target must be alive.
        if not is_player_alive(g, target_id):
            return False, 'Not allowed.'

        return True, '' # no message

    def seer():
        # Player making command must be in the game.
        # 'you are not in the game.'

        # Player must be alive.
        # 'you are not alive.'

        # Player must be the seer

        # Must be night.

        # Must not have already used power that night.

        return False, None

    u = UserMap()

    if target_name==None:
        """
        No current role that
        has no target.
        """
        return False, 'need a target.'

    # turn target name into an id
    if u:
        # if we have access to user map
        target_id = u.get(name=target_name)
        user_name = u.get(user_id)
        if not target_id and target_name != 'pass':
            return False, 'User not in the game.' # user not in usermap

    if action == 'vote':
        return vote()
    elif action == 'kill':
        return kill()
    elif action == 'seer':
        # Not implemented yet.
        return seer()
    else:
        # Not valid
        return False, 'not a valid action'
def list_players(game_state, user_id, *kwargs):
    """List all the current players in the game."""
    user_map = UserMap()
    players = status.players_in_game(game_state)

    return '\n'.join([user_map.get(user_id=player_id) + ' | ' + status.player_status(game_state, player_id) for player_id in players]), None