def debug(game, stdscr): """ Dump state for debugging. """ player_cards = game.query_player_cards() lines = [] lines.append("Player cards:") for player, card in player_cards.items(): lines.append("{} -> {}".format(player, WerewolfGame.get_card_name(card))) lines.append("Table cards:") table_cards = game.query_table_cards() for n, card in enumerate(table_cards): lines.append("Table {} -> {}".format(n+1, WerewolfGame.get_card_name(card))) text = '\n'.join(lines) display_text(stdscr, text, title="DEBUG Info")
def show_cards_in_game(stdscr, game): """ Show what cards will be used in the game. """ cards = game.query_cards() card_counts = collections.Counter() for card in cards: card_name = WerewolfGame.get_card_name(card) card_counts[card_name] += 1 card_counts = card_counts.items() card_counts.sort() col_width = max(len(n) for n, c in card_counts) + 3 count_width = 3 lines = [] lines.append("======================") lines.append("Cards Used in the Game") lines.append("======================") lines.append(" ") for card_name, count in card_counts: lines.append("* {} x{}".format(card_name.rjust(col_width), str(count).rjust(3))) msg = '\n'.join(lines) display_text( stdscr, msg, title="= Setup =", keys=[curses.KEY_ENTER, 10, 13], key_message="= Press ENTER =")
def wake_up_insomniac(stdscr, game, player): """ Notify insomniac what her current card is. """ card = game.insomniac_view_card() card_name = WerewolfGame.get_card_name(card) msg = textwrap.dedent("""\ {}, your card is {}. """).format(player, card_name) display_text( stdscr, msg, title="Insomniac Phase", keys=[curses.KEY_ENTER, 10, 13], key_message="= Press ENTER =")
def show_roles_to_players(game, players, stdscr): """ Show each player the role he or she was dealt. """ player_cards = game.query_player_cards() for player in players: display_text( stdscr, "{}'s turn.".format(player), title="The Deal", keys=[curses.KEY_ENTER, 10, 13], key_message="= Press ENTER =") display_text( stdscr, "{} was dealt {}".format(player, WerewolfGame.get_card_name(player_cards[player])), title="The Deal", keys=[curses.KEY_ENTER, 10, 13], key_message="= Press ENTER =")
def use_robber_power(stdscr, game, players, player): """ Use the Robber's power to steal a card. """ lines = [] player_map = {} lines.append("{}, exchange your Robber card for another player's card.".format(player)) lines.append("Exchange with which player?") lines.append("1) I'll keep my card.") n = 2 for oplayer in players: if oplayer == player: continue lines.append("{}) {}".format(n, oplayer)) player_map[n] = oplayer n += 1 msg = '\n'.join(lines) player_map[1] = player keys = [ord("{}".format(n)) for n in player_map.keys()] rval = display_text( stdscr, msg, title="Robber Phase", keys=keys, key_message="= Choose an Option =") if int(chr(rval)) == 1: return oplayer = player_map[int(chr(rval))] stolen_card = game.robber_steal_card(oplayer) card_name = WerewolfGame.get_card_name(stolen_card) display_text( stdscr, "{}, you stole the {} card from {}!".format(player, card_name, oplayer), title="Robber Phase", keys=[curses.KEY_ENTER, 10, 13], key_message="= Press ENTER =")
def choose_seer_power(stdscr, game, players, player): msg = textwrap.dedent("""\ {}, choose: 1) Look at a player's card. 2) Look at 2 table cards. """).format(player) rval = display_text( stdscr, msg, title="Seer Phase", keys=[ord("1"), ord("2")], key_message="= Choose 1 or 2 =") if rval == ord("1"): lines = [] lines.append("View which player's card?") lines.append("") n = 1 keys = [] oplayer_map = {} for oplayer in players: if oplayer == player: continue lines.append("{}) {}".format(n, oplayer)) key_code = ord("{}".format(n)) keys.append(key_code) oplayer_map[key_code] = oplayer n += 1 rval = display_text( stdscr, '\n'.join(lines), title="Seer Phase", keys=keys, key_message="= Choose a player =") oplayer = oplayer_map[rval] card_code = game.seer_view_player_card(oplayer) card_name = WerewolfGame.get_card_name(card_code) display_text( stdscr, "{}'s card is {}.".format(oplayer, card_name), title="Seer Phase") elif rval == ord("2"): all_choices = [ord("1"), ord("2"), ord("3")] chosen = [] while len(chosen) != 2: if len(chosen) == 0: msg = "Choose a table card." else: msg = "Choose another table card." keys = [k for k in all_choices if k not in chosen] key_message = "= Choose {} =".format(', '.join(chr(k) for k in keys)) rval = display_text( stdscr, msg, title="Seer Phase", keys=keys, key_message=key_message) chosen.append(rval) choices = [int(chr(code)) - 1 for code in chosen] cards = game.seer_view_table_cards(*choices) card_names = [WerewolfGame.get_card_name(card) for card in cards] msg = textwrap.dedent("""\ Your mystic powers reveal the following table cards: * Card {} is {}. * Card {} is {}. """).format(choices[0]+1, card_names[0], choices[1]+1, card_names[1]) display_text( stdscr, msg, title="Seer Phase")
def display_post_game_results(stdscr, game, players): """ Display post-game results. """ results = game.query_post_game_results() winning_team = results.winner if winning_team == WerewolfGame.WINNER_VILLAGE: title = "Village Victory!" elif winning_team == WerewolfGame.WINNER_TANNER_AND_VILLAGE: title = "Village & Tanner Victory!" elif winning_team == WerewolfGame.WINNER_TANNER: title = "Tanner Victory!" elif winning_team == WerewolfGame.WINNER_WEREWOLVES: title = "Werewolf Victory!" elif winning_team == WerewolfGame.WINNER_NO_ONE: title = "No one wins!" else: raise Exception("Unknown winner code {}".format(winning_team)) player_result_matrix = [] for player in players: entry = ( player, WerewolfGame.get_card_name(results.orig_player_cards[player]), WerewolfGame.get_card_name(results.player_cards[player])) player_result_matrix.append(entry) table_result_matrix = zip( [WerewolfGame.get_card_name(c) for c in results.orig_table_cards], [WerewolfGame.get_card_name(c) for c in results.table_cards]) lines = [] col_width = 20 col_space = 2 lines.append("- Player Results -".center(col_width * 3)) lines.append(" ") lines.append("{}{}{}".format( "Player".ljust(col_width), "Dealt Card".ljust(col_width), "Final Card".ljust(col_width))) lines.append("{}{}{}".format( ("=" * (col_width - col_space)).ljust(col_width), ("=" * (col_width - col_space)).ljust(col_width), ("=" * (col_width - col_space)).ljust(col_width))) cycle_it = itertools.cycle([False, True]) for highlight, (player, dealt, final) in six.moves.zip(cycle_it, player_result_matrix): lines.append("{}{}{}".format( player.ljust(col_width), dealt.ljust(col_width), final.ljust(col_width))) lines.append(" ") lines.append("- Cards Dealt to the Table -".center(col_width * 3)) lines.append(" ") lines.append("{}{}{}".format( "Table Spot".ljust(col_width), "Dealt Card".ljust(col_width), "Final Card".ljust(col_width))) lines.append("{}{}{}".format( ("=" * (col_width - col_space)).ljust(col_width), ("=" * (col_width - col_space)).ljust(col_width), ("=" * (col_width - col_space)).ljust(col_width))) cycle_it = itertools.cycle([False, True]) for n, (highlight, (dealt, final)) in enumerate(six.moves.zip(cycle_it, table_result_matrix)): lines.append("{}{}{}".format( ("Card {}".format(n + 1)).ljust(col_width), dealt.ljust(col_width), final.ljust(col_width))) display_text( stdscr, '\n'.join(lines), title=title)
def main(stdscr, args): """ Configure and run the werewolf game. """ players = args.player werewolf_count, other_roles = parse_roles(args) game = WerewolfGame() game.add_players(players) game.deal_cards(werewolf_count, other_roles) display_title(stdscr) msg = """The village has been invaded by ghastly werewolves! These bloodthirsty shape changers want to take over the village. But the villagers know they are weakest at daybreak, and that is when they will strike at their enemy. In this game, you will take on the role of a villager or a werewolf. At daybreak, the entire village votes on who lives and who dies. If a werewolf is slain, the villagers win. If no werewolves are slain, the werewolf team wins. If no players are werewolves, the villagers only win if no one dies.""" display_text(stdscr, msg, title="Instructions for Play") if args.debug: debug(game, stdscr) show_cards_in_game(stdscr, game) show_roles_to_players(game, players, stdscr) phase = None while True: game.advance_phase() phase = game.query_phase() clear_screen() if phase == "Daybreak": break if not game.is_role_active(): continue for player in players: start_player_turn(stdscr, player, phase) if not game.is_player_active(player): show_player_asleep(stdscr, player, phase) elif phase == "Werewolf Phase": show_werewolves_to_player(stdscr, game, player, phase) elif phase == "Minion Phase": show_werewolves_to_player(stdscr, game, player, phase) elif phase == "Seer Phase": choose_seer_power(stdscr, game, players, player) elif phase == "Robber Phase": use_robber_power(stdscr, game, players, player) elif phase == "Troublemaker Phase": use_troublemaker_power(stdscr, game, players, player) elif phase == "Insomniac Phase": wake_up_insomniac(stdscr, game, player) else: raise Exception("Unknown phase, {}".format(phase)) show_daybreak_message(stdscr) vote_to_eliminate(stdscr, game, players) display_post_game_results(stdscr, game, players)