async def end_game(self):
     """End the game, compute winners etc. 
   Must be implemented.
   """
     # Send the lobby game conclusion message
     await self.send_lobby_closing_message()
     # Remove roles
     await botutils.remove_all_alive_dead_roles_after_game()
     # Unload extensions
     globvars.client.unload_extension("botc.commands.abilities")
     globvars.client.unload_extension("botc.commands.townhall")
     globvars.client.unload_extension("botc.commands.debug")
     # Load conflicting commands
     for extension in CONFLICTING_CMDS:
         globvars.client.load_extension(extension)
     # Log the game
     await botutils.log(botutils.Level.info, "Game finished")
     # Stop various loops from running
     from botc.gameloops import nomination_loop, base_day_loop
     # Stop the nomination loop if it is running
     if nomination_loop.is_running():
         nomination_loop.cancel()
     # Stop the base day loop if it is running
     if base_day_loop.is_running():
         base_day_loop.cancel()
     # Clear the game object
     self.__init__()
     globvars.master_state.game = None
     # Unlock the lobby channel
     await botutils.unlock_lobby()
     # Update the global state
     botutils.update_state_machine()
    async def make_nightfall(self):
        """Transition the game into night phase"""

        # Initialize the master switches at the start of a phase
        import botc.switches
        botc.switches.init_switches()

        # Initialize the temporary night data set
        self.init_temporary_night_data()

        # Stop all tasks of the day phase
        if nomination_loop.is_running():
            nomination_loop.cancel()
        if base_day_loop.is_running():
            base_day_loop.cancel()

        # Move the chrono forward by one phase
        self._chrono.next()

        # Prepare the phase announcement message
        embed = discord.Embed(description=nightfall, color=CARD_NIGHT)
        embed.set_footer(text=copyrights_str)
        embed.set_image(url=nightfall_image)
        embed.timestamp = datetime.datetime.utcnow()
        await botutils.send_lobby(message="", embed=embed)

        # Reset the nomination data for the previous day phase
        for player in self.sitting_order:
            player.reset_nomination()
    async def fstop(self, ctx):
        """Fstop command"""

        from botc.gameloops import nomination_loop, base_day_loop, debate_timer

        # Stop the nomination loop if it is running
        if nomination_loop.is_running():
            nomination_loop.cancel()

        # Stop the base day loop if it is running
        if base_day_loop.is_running():
            base_day_loop.cancel()

        # Stop the debate timer loop if it is running
        if debate_timer.is_running():
            debate_timer.cancel()

        # Stop the gameplay loop if it is running
        import globvars
        if globvars.master_state.game.gameloop.is_running():
            globvars.master_state.game.gameloop.cancel()
            feedback = documentation["doc"]["fstop"]["feedback"]
            await ctx.send(feedback.format(botutils.BotEmoji.check))
        else:
            feedback = documentation["cmd_warnings"]["no_game_running"]
            await ctx.send(
                feedback.format(ctx.author.mention, botutils.BotEmoji.cross))
Exemple #4
0
    async def fnight(self, ctx):
        """Fnight command"""

        import globvars
        if globvars.master_state.game.current_phase == Phase.day:

            from botc.gameloops import (base_day_loop, debate_timer,
                                        nomination_loop)

            # Stop the nomination loop if it is running
            if nomination_loop.is_running():
                nomination_loop.cancel()

            # Stop the base day loop if it is running
            if base_day_loop.is_running():
                base_day_loop.cancel()

            # Stop the debate timer loop if it is running
            if debate_timer.is_running():
                debate_timer.cancel()

            import botc.switches
            botc.switches.master_proceed_to_night = True
            msg = game_text["doc"]["fnight"]["feedback"].format(
                botutils.BotEmoji.success)

            await ctx.send(msg)
Exemple #5
0
    async def fnomination(self, ctx):
        """fnomination command"""

        import globvars
        if globvars.master_state.game.current_phase == Phase.day:
            from botc.gameloops import base_day_loop
            if base_day_loop.is_running():
                base_day_loop.cancel()
                import botc.switches
                botc.switches.master_proceed_to_nomination = True
                msg = game_text["doc"]["fnomination"]["feedback"].format(botutils.BotEmoji.success)
                await ctx.send(msg)
    async def nominate(self, ctx, *, nominated: PlayerConverter()):
        """Nominate command
        usage: nominate <player> 
        characters: living players
        """
        import globvars
        from botc.gameloops import nomination_loop, base_day_loop
        player = BOTCUtils.get_player_from_id(ctx.author.id)

        # A nomination is currently going on. The player cannot nominate.
        if nomination_loop.is_running():
            msg = nomination_ongoing.format(ctx.author.mention,
                                            botutils.BotEmoji.cross)
            await ctx.send(msg)
            return

        # The day has not reached nomination phase yet. The player cannot nominate.
        elif base_day_loop.is_running():
            msg = nominations_not_open.format(ctx.author.mention,
                                              botutils.BotEmoji.cross)
            await ctx.send(msg)
            return

        if player.can_nominate():
            if nominated.can_be_nominated():
                # The player cannot nominate again today
                player.toggle_has_nominated()
                # The nominated player cannot be nominated again today
                nominated.toggle_was_nominated()
                await nominated.role.true_self.on_being_nominated(
                    player, nominated)
            else:
                msg = cannot_be_nominated_again.format(ctx.author.mention,
                                                       botutils.BotEmoji.cross,
                                                       nominated.game_nametag)
                await ctx.send(msg)
        else:
            msg = cannot_nominate_again.format(ctx.author.mention,
                                               botutils.BotEmoji.cross)
            await ctx.send(msg)
Exemple #7
0
    async def votestop(self, ctx):
        """Votestop command"""

        import globvars

        if ctx.author.id in globvars.votestop_votes:
            return

        globvars.votestop_votes.append(ctx.author.id)

        votes_needed = math.ceil(len(globvars.master_state.game.player_obj_list) / 2)

        if not votestop_votes_timer.is_running():
            votestop_votes_timer.start()

        await send_lobby(votestop_vote.format(ctx.author.mention, votes_needed - len(globvars.votestop_votes), "" if votes_needed - len(globvars.votestop_votes) == 1 else "s"))

        if len(globvars.votestop_votes) >= votes_needed:
            votestop_votes_timer.cancel()

            from botc.gameloops import (base_day_loop, debate_timer,
                                        nomination_loop)

            # Stop the nomination loop if it is running
            if nomination_loop.is_running():
                nomination_loop.cancel()

            # Stop the base day loop if it is running
            if base_day_loop.is_running():
                base_day_loop.cancel()

            # Stop the debate timer loop if it is running
            if debate_timer.is_running():
                debate_timer.cancel()

            # Stop the gameplay loop if it is running
            import globvars
            if globvars.master_state.game.gameloop.is_running():
                globvars.master_state.game.gameloop.cancel()
Exemple #8
0
    async def sync(self, ctx):
        """Sync command"""

        # Case 1 : Game softlock
        if globvars.master_state.game and not globvars.master_state.game.gameloop.is_running(
        ) and not globvars.master_state.game.working:
            from botc.gamemodes.Gamemode import Gamemode

            globvars.master_state.game.invalidated = True
            try:
                await botutils.unlock_lobby()

                alive_role = globvars.client.get_guild(SERVER_ID).get_role(
                    ALIVE_ROLE_ID)
                dead_role = globvars.client.get_guild(SERVER_ID).get_role(
                    DEAD_ROLE_ID)

                for player in alive_role.members:
                    await botutils.remove_alive_role(player)
                for player in dead_role.members:
                    await botutils.remove_dead_role(player)
            except Exception as e:
                print(e)

            try:
                if globvars.master_state.game.gamemode == Gamemode.trouble_brewing:
                    globvars.client.unload_extension(
                        "botc.commands.abilities.tb")
                elif globvars.master_state.game.gamemode == Gamemode.bad_moon_rising:
                    globvars.client.unload_extension(
                        "botc.commands.abilities.bmr")
                elif globvars.master_state.game.gamemode == Gamemode.sects_and_violets:
                    globvars.client.unload_extension(
                        "botc.commands.abilities.snv")

                globvars.client.unload_extension("botc.commands.townhall")
                globvars.client.unload_extension("botc.commands.debug")
            except Exception as e:
                print(e)

            from botc.gameloops import (base_day_loop, master_game_loop,
                                        nomination_loop)

            try:
                # Stop the nomination loop if it is running
                if nomination_loop.is_running():
                    nomination_loop.cancel()
                # Stop the base day loop if it is running
                if base_day_loop.is_running():
                    base_day_loop.cancel()

                if master_game_loop.is_running():
                    master_game_loop.cancel()
            except Exception as e:
                print(e)

            try:
                from botc.Game import CONFLICTING_CMDS
                for cmd in CONFLICTING_CMDS:
                    globvars.client.load_extension(cmd)
            except Exception:
                pass

            globvars.master_state.game = None

            botutils.update_state_machine()

        elif not globvars.master_state.game:
            try:
                await botutils.unlock_lobby()

                dead_role = globvars.client.get_guild(SERVER_ID).get_role(
                    DEAD_ROLE_ID)
                for player in dead_role.members:
                    await botutils.remove_dead_role(player)

                alive_role = globvars.client.get_guild(SERVER_ID).get_role(
                    ALIVE_ROLE_ID)
                mismatched_alive_players = list(
                    filter(
                        lambda user: user.id not in globvars.master_state.
                        pregame.list, alive_role.members))
                for member in mismatched_alive_players:
                    await member.remove_roles(alive_role)

                await botutils.add_all_alive_role()
            except Exception:
                pass

            try:
                from botc.Game import CONFLICTING_CMDS
                for cmd in CONFLICTING_CMDS:
                    globvars.client.load_extension(cmd)
            except Exception:
                pass

            try:
                await botutils.unlock_lobby()
            except Exception:
                pass

            botutils.update_state_machine()
        elif globvars.master_state.game:
            await botutils.add_all_alive_role()

        await ctx.send(
            sync_succesful_string.format(ctx.author.mention,
                                         botutils.BotEmoji.success))
Exemple #9
0
    async def time(self, ctx):
        """Time command
        usage: time
        can be used by all players or in DM
        """
        import globvars

        # Day phase
        if globvars.master_state.game.current_phase == Phase.day:

            # Day phase: pre-nomination (base day phase)
            if base_day_loop.is_running():

                start_time = base_day_loop.next_iteration
                total_duration = calculate_base_day_duration(
                    globvars.master_state.game)
                __time_elapsed = (
                    datetime.datetime.now(datetime.timezone.utc) -
                    start_time).seconds
                time_left = total_duration - __time_elapsed

                msg = time_day_base.format(
                    display_time(total_duration), "is" if time_left == 1 or
                    (time_left >= 60 and time_left < 120) else "are",
                    display_time(time_left))

                await ctx.send(msg)

            # Day phase: nomination loop is running
            elif nomination_loop.is_running():

                # We are in the debate phase
                if debate_timer.is_running():
                    end_time = debate_timer.next_iteration
                    total_duration = DEBATE_TIME
                    time_left = (
                        end_time -
                        datetime.datetime.now(datetime.timezone.utc)).seconds
                    msg = time_debate.format(display_time(total_duration),
                                             display_time(time_left))
                    await ctx.send(msg)

                # We are in the active voting phase
                else:
                    msg = time_voting
                    await ctx.send(msg)

            # Day phase: waiting for a nomination
            else:
                start_time = globvars.master_state.game.nomination_iteration_date[
                    0]
                duration = globvars.master_state.game.nomination_iteration_date[
                    1]
                time_left = duration - (datetime.datetime.now() -
                                        start_time).seconds
                msg = time_nomination.format(display_time(duration),
                                             display_time(time_left))
                await ctx.send(msg)

        # Night phase
        elif globvars.master_state.game.current_phase == Phase.night:

            min_night_duration = BASE_NIGHT
            max_night_duration = BASE_NIGHT + NIGHT_MULTIPLER * INCREMENT
            __time_elapsed = (
                datetime.datetime.now() -
                globvars.master_state.game.night_start_time).seconds
            time_left = max_night_duration - __time_elapsed

            msg = time_night.format(
                display_time(min_night_duration),
                display_time(max_night_duration), "is" if time_left == 1 or
                (time_left >= 60 and time_left < 120) else "are",
                display_time(time_left))

            await ctx.send(msg)

        # Dawn phase
        elif globvars.master_state.game.current_phase == Phase.dawn:

            min_dawn_duration = BASE_DAWN
            max_dawn_duration = BASE_DAWN + DAWN_MULTIPLIER * INCREMENT
            __time_elapsed = (
                datetime.datetime.now() -
                globvars.master_state.game.dawn_start_time).seconds
            time_left = max_dawn_duration - __time_elapsed

            msg = time_dawn.format(
                display_time(min_dawn_duration),
                display_time(max_dawn_duration), "is" if time_left == 1 or
                (time_left >= 60 and time_left < 120) else "are",
                display_time(time_left))

            await ctx.send(msg)