def _check_valid_nominator(ctx: Context, nominator: Player, nominee: Player): """Check that nominator is a valid nominator, else raise an exception.""" if not ( nominator.can_nominate(ctx) or nominee.character_type(ctx) == "traveler" or nominator.character_type(ctx) == "storyteller" ): raise ValueError("nominator already nominated")
def _check_valid_nominee(game: "Game", nominator: Player, nominee: Player): """Check that the nominee is a valid nominee, else raise an exception.""" if nominee.is_status(game, "storyteller"): # atheist nominations for st in game.storytellers: if not st.can_be_nominated(game, nominator): raise commands.BadArgument( "The storytellers cannot be nominated today.") elif not nominee.can_be_nominated(game, nominator): raise commands.BadArgument( f"{nominee.nick} cannot be nominated today.")
def _check_valid_nominee(ctx: Context, nominator: Player, nominee: Player): """Check that the nominee is a valid nominee, else raise an exception.""" if nominee.character_type(ctx) == "storyteller": # atheist nominations for st in ctx.bot.game.storytellers: if not st.can_be_nominated(ctx, nominator): raise commands.BadArgument( "The storytellers cannot be nominated today." ) elif not nominee.can_be_nominated(ctx, nominator): raise commands.BadArgument(f"{nominee.nick} cannot be nominated today.")
async def _effect_adder( ctx: Context, player: Player, effect: Type[Effect.Effect], source: Player = None ): """Add effect to player.""" source = source or player effect_object = player.add_effect(ctx, effect, source) if source == player or source.character_type(ctx) == "storyteller": source_text = "" else: source_text = f"with source {source.nick} " await safe_send( ctx, f"Successfully added effect {effect_object.name} {source_text}to {player.nick}.", )
async def _effect_adder( ctx: "GameContext", player: Player, effect: Type[Effect.Effect], source: Player = None, ): """Add effect to player.""" source = source or player effect_object = player.add_effect(ctx.bot.game, effect, source) if source == player or source.is_status(ctx.bot.game, "storyteller"): source_text = "" else: source_text = f"with source {source.nick} " await safe_send( ctx, f"Added effect {effect_object.name} {source_text}to {player.nick}.", )
async def nomination( self, ctx: "Context", nominee: Player, nominator: Player, enabled: bool = True, epithet_string: str = "", ) -> bool: """Handle Virgin nomination. If nominee is the Virgin and nominator is a townsfolk, execute nominator. """ if nominee == self.parent: self.parent.add_effect(ctx, UsedAbility, self.parent) if enabled and nominator.is_status(ctx, "townsfolk", registers=True): await safe_send( ctx.bot.channel, generate_nomination_message_text( ctx, nominator, nominee, traveler=False, proceed=False ), ) await nominator.execute(ctx) return False return True
def _check_valid_nominator(game: "Game", nominator: Player, nominee: Player): """Check that nominator is a valid nominator, else raise an exception.""" if not (nominator.can_nominate(game) or nominee.is_status( game, "traveler") or nominator.is_status(game, "storyteller")): raise AlreadyNomniatedError
def _update_storyteller_list(bot, after, before): """Add new storytellers to the Storyteller list.""" if bot.storyteller_role not in before.roles and bot.storyteller_role in after.roles: bot.game.storytellers.append(Player(after, Storyteller, None)) bot.backup()
async def start_game(self, ctx: "Context", script: "Script"): """Handle startgame logic.""" await safe_send(ctx, f"Starting a {script.name} game.") # ask for the list of players users = await to_member_list( ctx, (await get_input( ctx, ("What is the seating order? (Separate " "users with line breaks. Do not include " "travelers.)"), )).split("\n"), ) # ask for the list of characters characters = to_character_list( ctx, (await get_input( ctx, ("What are the corresponding characters? " "(Separate characters with line breaks.)"), )).split("\n"), script, ) with ctx.typing(): # doing a lot of computation here # verify 1:1 user:character ratio if len(users) != len(characters): raise commands.BadArgument( "There are a different number of players and characters.") # role cleanup await self._startgame_role_cleanup(users) # generate seating order seating_order = [ Player(person, characters[index], index) for index, person in enumerate(users) ] # script message posts = [] for content in list(script.info(ctx)): posts.append(await safe_send(self.channel, content)) for post in posts[::-1]: # Reverse the order so the pins are right await post.pin() # welcome message await safe_send( self.channel, (f"{self.player_role.mention}, " "welcome to Blood on the Clocktower! Go to " "sleep."), ) # Seating order message seating_order_message = await safe_send( self.channel, generate_game_info_message(seating_order, ctx), ) await seating_order_message.pin() # storytellers storytellers = [ Player(person, Storyteller, None) for person in self.storyteller_role.members ] # start the game self.game = Game(seating_order, seating_order_message, script, storytellers) # complete return
async def addtraveler( self, ctx: Context, traveler: str, upwards_neighbor: str, alignment: str, *, character: str, ): """Add a traveler to the game. traveler: The player to join the game. character: Their traveler character. upwards_neighbor: The player above them in the seating order. alignment: The traveler's alignment; 'good' or 'evil'. """ # convert the traveler traveler_actual = await to_member(ctx, traveler) # check alignment is valid if not alignment.lower() in ["good", "evil"]: raise commands.BadArgument( "The alignment must be 'good' or 'evil' exactly.") # check if person is in the game try: get_player(ctx.bot.game, traveler_actual.id) raise commands.BadArgument( f"{load_preferences(traveler_actual).nick} is already in the game." ) except ValueError as e: if str(e) == "player not found": # find the character character_actual = to_character(ctx, character) # determine the position upwards_neighbor_actual = await to_player( ctx, upwards_neighbor) # make the Player player = Player( traveler_actual, character_actual, upwards_neighbor_actual.position + 1, ) # check that the character is a traveler if not player.character_type(ctx) == "traveler": raise commands.BadArgument( f"{player.character.name} is not a traveler.") # add the alignment if alignment.lower() == "good": player.add_effect(ctx, Good, player) elif alignment.lower() == "evil": player.add_effect(ctx, Evil, player) # add the player role await traveler_actual.add_roles(ctx.bot.player_role) # add them to the seating order ctx.bot.game.seating_order.insert( upwards_neighbor_actual.position + 1, player) # announcement await safe_send( ctx.bot.channel, ("{townsfolk}, {player} has joined the town as the {traveler}. " "Let's tell {pronoun} hello!").format( traveler=player.character.name, pronoun=load_preferences(player).pronouns[1], townsfolk=ctx.bot.player_role.mention, player=player.nick, ), ) # rules msg = await safe_send( ctx.bot.channel, f"\n**{player.character.name}** - {player.character.rules_text}", ) await msg.pin() await safe_send( ctx, f"Successfully added {player.nick} as the {player.character.name}.", ) else: raise