Esempio n. 1
0
    async def on_being_executed(self, executed_player):
        """Funtion that runs after the player has been executed.
        Overriding the parent behaviour.
        Check for presence of scarlet woman and promote her to demonhood if applicable.
        """
        if executed_player.is_alive():
            # If 5 or more players alive (not counting travelers), scarlet woman gets 
            # promoted to demonhood
            if globvars.master_state.game.nb_alive_players >= 5:

                from botc.gamemodes.troublebrewing import ScarletWoman
                # This list of scarletwomen could contain dead players
                scarletwomen = BOTCUtils.get_players_from_role_name(ScarletWoman()._role_enum)

                if scarletwomen:
                    # We only want the alive, and not poisoned scarlet women
                    alive_scarletwomen = [player for player in scarletwomen if player.is_alive() and not player.is_droisoned()]
                    if alive_scarletwomen:
                        promoted = random.choice(alive_scarletwomen)
                        promoted._old_role_obj = promoted._role_obj
                        await promoted.exec_change_role(Imp())
                        embed = self.__make_demonhood_promo_embed(promoted)
                        try:
                            await promoted.user.send(embed = embed)
                        except discord.Forbidden:
                            pass

            await executed_player.exec_real_death()
            game = globvars.master_state.game
            game.today_executed_player = executed_player
Esempio n. 2
0
    async def process_night_ability(self, player):
        """Process night actions for the imp character.
        @player : the Imp player (Player object)
        """

        # We only do any of the following if the imp is alive. Otherwise skip everything.
        if player.is_alive():
        
            phase = globvars.master_state.game._chrono.phase_id
            action = player.action_grid.retrieve_an_action(phase)
            # The imp has submitted an action. We call the execution function immediately
            if action:
                assert action.action_type == ActionTypes.kill, f"Wrong action type {action} in imp"
                targets = action.target_player
                killed_player = targets[0]
                await self.exec_kill(player, killed_player)
            # The imp has not submitted an action. We will randomize the action and make 
            # the imp kill one random player that is not the imp. 
            else:
                if player.is_alive():
                    killed_player = BOTCUtils.get_random_player_excluding(player)
                    await self.exec_kill(player, killed_player)
                    msg = botutils.BotEmoji.butterfly
                    msg += " "
                    msg += action_assign.format(killed_player.game_nametag)
                    try:
                        await player.user.send(msg)
                    except discord.Forbidden:
                        pass
                else:
                    pass
    def get_demon_bluffs(self):
        """Get the list of 3 demon bluffs"""

        # 3 demon bluffs: 2 townsfolk characters + 1 outsider character
        # Exclusing all characters taken by other players, as well as the drunk's ego_self
        all_townsfolks = BOTCUtils.get_role_list(TroubleBrewing, Townsfolk)
        all_outsiders = BOTCUtils.get_role_list(TroubleBrewing, Outsider)
        taken_townsfolks = [
            player.role.name
            for player in globvars.master_state.game.setup.townsfolks
        ]
        taken_outsiders = [
            player.role.name
            for player in globvars.master_state.game.setup.outsiders
        ]

        possible_townsfolk_bluffs = [
            character for character in all_townsfolks
            if character.name not in taken_townsfolks
        ]
        possible_outsider_bluffs = [
            character for character in all_outsiders
            if character.name not in taken_outsiders
        ]
        random.shuffle(possible_townsfolk_bluffs)
        random.shuffle(possible_outsider_bluffs)

        # For the first two bluffs, we want a townsfolk, definitely
        bluff_1 = possible_townsfolk_bluffs.pop()
        bluff_2 = possible_townsfolk_bluffs.pop()

        # For the third bluff, if the outsider list is not empty, we will take an outsider. Otherwise
        # it's 40% chance outsider, 60% chance townsfolk
        if possible_outsider_bluffs:
            town_or_out = random.choices(["t", "o"], weights=[0.6, 0.4])
            if town_or_out[0] == "t":
                bluff_3 = possible_townsfolk_bluffs.pop()
            else:
                bluff_3 = possible_outsider_bluffs.pop()
        else:
            bluff_3 = possible_townsfolk_bluffs.pop()

        globvars.logging.info(
            f">>> Imp: Received three demon bluffs {bluff_1}, {bluff_2} and {bluff_3}."
        )
        return (bluff_1, bluff_2, bluff_3)
Esempio n. 4
0
    async def _starpass(self, demon_player):
        """Starpassing ability works when the demon is killed by himself at night"""
        
        # If 5 or more players alive (not counting travelers), scarlet woman has priority 
        # over the promotion to demonhood
        if globvars.master_state.game.nb_alive_players >= 5:

            from botc.gamemodes.troublebrewing import ScarletWoman
            # This list of scarletwomen could contain dead players
            scarletwomen = BOTCUtils.get_players_from_role_name(ScarletWoman()._role_enum)

            if scarletwomen:
                # We only want the alive, and not poisoned scarlet women
                alive_scarletwomen = [player for player in scarletwomen if player.is_alive() and not player.is_droisoned()]
                if alive_scarletwomen:
                    promoted = random.choice(alive_scarletwomen)
                    promoted._old_role_obj = promoted._role_obj
                    await promoted.exec_change_role(Imp())
                    embed = self.__make_demonhood_promo_embed(promoted)
                    try:
                        await promoted.user.send(embed = embed)
                    except discord.Forbidden:
                        pass
                    return
        
        # Otherwise, any random minion is selected
        # This list of minions could contain dead players
        minions = BOTCUtils.get_all_minions()

        if minions:
            # We only want the alive players.
            alive_minions = [player for player in minions if player.is_alive()]
            if alive_minions:
                promoted = random.choice(alive_minions)
                promoted._old_role_obj = promoted._role_obj
                await promoted.exec_change_role(Imp())
                embed = self.__make_demonhood_promo_embed(promoted)
                try:
                    await promoted.user.send(embed = embed)
                except discord.Forbidden:
                    pass
Esempio n. 5
0
    async def modkill(self, ctx, *, player: PlayerConverter):
        """Modkill command"""
        if player.role.social_self.category == Category.demon:
            if player.is_alive():
                # If 5 or more players alive (not counting travelers), scarlet woman gets
                # promoted to demonhood
                if globvars.master_state.game.nb_alive_players >= 5:

                    from botc.gamemodes.troublebrewing import ScarletWoman

                    # This list of scarletwomen could contain dead players
                    scarletwomen = BOTCUtils.get_players_from_role_name(
                        ScarletWoman()._role_enum)

                    if scarletwomen:
                        # We only want the alive, and not poisoned scarlet women
                        alive_scarletwomen = [
                            player for player in scarletwomen
                            if player.is_alive() and not player.is_droisoned()
                        ]
                        if alive_scarletwomen:
                            promoted = random.choice(alive_scarletwomen)
                            promoted._old_role_obj = promoted._role_obj
                            await promoted.exec_change_role(Imp())

                            if not DISABLE_DMS:
                                embed = Imp._make_demonhood_promo_embed(
                                    Imp(), promoted)
                                try:
                                    await promoted.user.send(embed=embed)
                                except discord.Forbidden:
                                    pass

        await player.exec_real_death()
        player.ghost_vote = 0
        if not NO_INVALIDATE:
            globvars.master_state.game.invalidated = True
        feedback = game_text["doc"]["modkill"]["feedback"]
        await ctx.send(feedback.format(check_emoji, player.game_nametag))
Esempio n. 6
0
    async def exec_slay(self, slayer_player, slain_player):
        """Execute the slay action (immediate effect)"""

        # Remove the unique use ability from the player's inventory
        slayer_player.role.ego_self.inventory.remove_item_from_inventory(Flags.slayer_unique_attempt)
        slayer_player.add_persistent_reminder_token('botc/assets/tb_reminder_tokens_cropped/slayer_used.png')

        # The ability succeeds when the slayer is not droisoned and the slain player is registering
        # as a demon with their social self
        if not slayer_player.is_droisoned():
            if slain_player.role.social_self.category == Category.demon:
                string = LorePicker().pick(LorePicker().SLAY_SUCCESS)
                string = string.format(
                    slayer = slayer_player.game_nametag,
                    slain = slain_player.game_nametag
                )

                if slain_player.is_alive():

                    # Add information to replay
                    globvars.master_state.game.replay += f"- {slayer_player.user.name} (Slayer) "\
                                f"slays {slain_player.user.name} ({slain_player.role.true_self}, "\
                                f"registering as {slain_player.role.social_self})\n"

                    # If 5 or more players alive (not counting travelers), scarlet woman gets
                    # promoted to demonhood
                    if globvars.master_state.game.nb_alive_players >= 5:

                        from botc.gamemodes.troublebrewing import ScarletWoman

                        # This list of scarletwomen could contain dead players
                        scarletwomen = BOTCUtils.get_players_from_role_name(ScarletWoman()._role_enum)

                        if scarletwomen:
                            # We only want the alive, and not poisoned scarlet women
                            alive_scarletwomen = [player for player in scarletwomen if player.is_alive() and not player.is_droisoned()]
                            if alive_scarletwomen:
                                promoted = random.choice(alive_scarletwomen)

                                # Add information to replay
                                globvars.master_state.game.replay += f"- {promoted.user.name} "\
                                                                    "(Scarlet Woman) becomes Imp\n"

                                promoted._old_role_obj = promoted._role_obj
                                await promoted.exec_change_role(Imp())

                                if not DISABLE_DMS:
                                    embed = Imp._make_demonhood_promo_embed(Imp(), promoted)
                                    try:
                                        await promoted.user.send(embed = embed)
                                    except discord.Forbidden:
                                        pass

                    try:
                        await slain_player.exec_real_death()
                    except AlreadyDead:
                        pass
                    await botutils.send_lobby(string)
                    return

        # Add information to replay
        drunk = "Drunk " if slayer_player.role.true_self.name == Drunk().name else ""
        globvars.master_state.game.replay += f"- {slayer_player.user.name} ({drunk}Slayer) "\
                                            f"unsuccessfully slays {slain_player.user.name} "\
                                            f"({slain_player.role.true_self}, registering "\
                                            f"as {slain_player.role.social_self})\n"

        # The ability fails no matter what for a droisoned slayer, or if the slain player
        # is not a demon
        string = LorePicker().pick(LorePicker().SLAY_FAIL)
        string = string.format(
            slayer = slayer_player.game_nametag,
            slain = slain_player.game_nametag
        )
        await botutils.send_lobby(string)
Esempio n. 7
0
    async def _starpass(self, demon_player):
        """Starpassing ability works when the demon is killed by himself at night"""

        # If imp starpasses to poisoner, the poisoned player should be no longer poisoned
        for player in globvars.master_state.game.sitting_order:
            for status in player.status_effects:
                if status.effect == StatusList.poison:
                    status.manually_disable()

        # If 5 or more players alive (not counting travelers), scarlet woman has priority
        # over the promotion to demonhood
        if globvars.master_state.game.nb_alive_players >= 5:

            from botc.gamemodes.troublebrewing import ScarletWoman

            # This list of scarletwomen could contain dead players
            scarletwomen = BOTCUtils.get_players_from_role_name(
                ScarletWoman()._role_enum)

            if scarletwomen:
                # We only want the alive, and not poisoned scarlet women
                alive_scarletwomen = [
                    player for player in scarletwomen
                    if player.is_alive() and not player.is_droisoned()
                ]
                if alive_scarletwomen:
                    promoted = random.choice(alive_scarletwomen)

                    # Add information to replay
                    globvars.master_state.game.replay += f"- {promoted.user.name} (Scarlet Woman) "\
                                                        "becomes Imp\n"

                    promoted._old_role_obj = promoted._role_obj
                    await promoted.exec_change_role(Imp())
                    promoted.add_persistent_reminder_token(
                        'botc/assets/tb_reminder_tokens_cropped/sw_demon.png')

                    if DISABLE_DMS:
                        return

                    embed = self._make_demonhood_promo_embed(promoted)
                    try:
                        await promoted.user.send(embed=embed)
                    except discord.Forbidden:
                        pass
                    return

        # Otherwise, any random minion is selected
        # This list of minions could contain dead players
        minions = BOTCUtils.get_all_minions()

        if minions:
            # We only want the alive players.
            alive_minions = [player for player in minions if player.is_alive()]
            if alive_minions:
                promoted = random.choice(alive_minions)

                # Add information to replay
                globvars.master_state.game.replay += f"- {promoted.user.name} "\
                                                    f"({promoted.role.true_self}) becomes Imp\n"

                promoted._old_role_obj = promoted._role_obj
                await promoted.exec_change_role(Imp())
                promoted.add_persistent_reminder_token(
                    'botc/assets/tb_reminder_tokens_cropped/sw_demon.png')

                if DISABLE_DMS:
                    return

                embed = self._make_demonhood_promo_embed(promoted)
                try:
                    await promoted.user.send(embed=embed)
                except discord.Forbidden:
                    pass