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
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