Example #1
0
    async def quit(self, ctx):
        """Quit command"""

        import globvars

        if globvars.master_state.game:
            # This check is to ensure a player doesn't quit right after !start
            # before the game is fully set up and end up breaking the game.
            return
        
        # The command user has joined; make them quit
        if globvars.master_state.pregame.is_joined(ctx.author.id):
            globvars.master_state.pregame.safe_remove_player(ctx.author.id)
            botutils.update_state_machine()
            await ctx.send(quit_str.format(ctx.author.name, len(globvars.master_state.pregame)))
            # If you are the last player to leave, then cancel the lobby timeout loop
            if len(globvars.master_state.pregame) == 0:
                lobby_timeout.cancel()
            # If the player has voted to start, then remove the start vote
            if ctx.author.id in globvars.start_votes:
                globvars.start_votes.remove(ctx.author.id)
            # Cancel the start clear timer if no one has voted to start
            if len(globvars.start_votes) == 0 and start_votes_timer.is_running():
                start_votes_timer.cancel()

        # The command user has not joined
        else:
            await ctx.send(quitted_str.format(ctx.author.mention))
        
        # Still take away the role from everyone just in case of discord sync issue
        await botutils.remove_alive_role(ctx.author, unlock=True)
 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()
Example #3
0
    async def fstart(self, ctx):
        """Force start command"""

        import globvars

        game = botutils.GameChooser().get_selected_game()

        # Make sure all the players are still in the guild
        globvars.master_state.pregame.remove_left_guild_players()

        if len(globvars.master_state.pregame) < game.MIN_PLAYERS:
            msg = fstart_min.format(ctx.author.mention,
                                    botutils.BotEmoji.x_emoji, str(game),
                                    game.MIN_PLAYERS)
            await ctx.send(msg)
            return

        if len(globvars.master_state.pregame) > game.MAX_PLAYERS:
            msg = fstart_max.format(ctx.author.mention,
                                    botutils.BotEmoji.x_emoji, str(game),
                                    game.MAX_PLAYERS)
            await ctx.send(msg)
            return

        globvars.master_state.game = game
        await globvars.master_state.game.start_game()
        botutils.update_state_machine()

        # Clear the start votes
        globvars.start_votes.clear()
    async def fleave(self, ctx, *, member: discord.Member):
        """Force leave command"""

        import globvars

        # The player has joined; make them leave
        if globvars.master_state.pregame.is_joined(member.id):
            globvars.master_state.pregame.safe_remove_player(member.id)
            await ctx.send(
                fleave_str.format(member.name,
                                  len(globvars.master_state.pregame)))
            botutils.update_state_machine()
            # If you are the last player to leave, then cancel the lobby timeout loop
            if len(globvars.master_state.pregame) == 0:
                lobby_timeout.cancel()
            # If the player has voted to start, then remove the start vote
            if member.id in globvars.start_votes:
                globvars.start_votes.remove(member.id)
            # Cancel the start clear timer if no one has voted to start
            if len(globvars.start_votes) == 0 and start_votes_timer.is_running(
            ):
                start_votes_timer.cancel()

        # The player has not joined
        else:
            await ctx.send(fleaved_str.format(ctx.author.mention, member.name))

        await botutils.remove_alive_role(member, unlock=True)
    async def start(self, ctx):
        """Start command"""

        import globvars

        # The player has already voted to start
        if ctx.author.id in globvars.start_votes:
            return

        game = botutils.GameChooser().get_selected_game()

        if len(globvars.master_state.pregame) < game.MIN_PLAYERS:
            msg = fstart_min.format(ctx.author.mention,
                                    botutils.BotEmoji.cross, str(game),
                                    game.MIN_PLAYERS)
            await ctx.send(msg)
            return

        if len(globvars.master_state.pregame) > game.MAX_PLAYERS:
            msg = fstart_max.format(ctx.author.mention,
                                    botutils.BotEmoji.cross, str(game),
                                    game.MAX_PLAYERS)
            await ctx.send(msg)
            return

        # The player has not voted to start yet
        else:

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

            # First person to vote. Start the clear start votes timer
            if len(globvars.start_votes) == 1:
                if start_votes_timer.is_running():
                    start_votes_timer.cancel()
                start_votes_timer.start()

            # Calculate the number of votes needed
            votes_needed = max(len(globvars.master_state.pregame) - 3, 3)

            # Reached the number of votes needed. Start the game.
            if len(globvars.start_votes) == votes_needed:
                game = botutils.GameChooser().get_selected_game()
                globvars.master_state.game = game
                await globvars.master_state.game.start_game()
                botutils.update_state_machine()

                # Clear the start votes
                globvars.start_votes.clear()

                return

            votes_left = votes_needed - len(globvars.start_votes)

            # Do not have a negative number of votes required to start
            if votes_left < 0:
                return

            msg = start_str.format(ctx.author.name, votes_left,
                                   "vote" if votes_left == 1 else "votes")
            await ctx.send(msg)
    async def fstart(self, ctx):
        """Force start command"""

        import globvars

        game = botutils.GameChooser().get_selected_game()

        if len(globvars.master_state.pregame) < game.MIN_PLAYERS:
            msg = fstart_min.format(ctx.author.mention,
                                    botutils.BotEmoji.cross, str(game),
                                    game.MIN_PLAYERS)
            await ctx.send(msg)
            return

        if len(globvars.master_state.pregame) > game.MAX_PLAYERS:
            msg = fstart_min
            msg = fstart_min.format(ctx.author.mention,
                                    botutils.BotEmoji.cross, str(game),
                                    game.MAX_PLAYERS)
            await ctx.send(msg)
            return

        globvars.master_state.game = game
        await globvars.master_state.game.start_game()
        botutils.update_state_machine()
    async def fjoin(self, ctx, *, member: discord.Member):
        """Force join command"""

        import globvars

        game = botutils.GameChooser().get_selected_game()

        # Too many players
        if len(globvars.master_state.pregame) >= game.MAX_PLAYERS:
            msg = fjoin_max
            msg = fjoin_max.format(ctx.author.mention, botutils.BotEmoji.cross,
                                   str(game), game.MAX_PLAYERS)
            await ctx.send(msg)
            return

        # The player has already joined
        if globvars.master_state.pregame.is_joined(member.id):
            await ctx.send(fjoined_str.format(ctx.author.mention, member.name))

        # The player has not yet joined. Make them join.
        else:
            globvars.master_state.pregame.safe_add_player(member.id)
            botutils.update_state_machine()
            await ctx.send(
                fjoin_str.format(member.name,
                                 len(globvars.master_state.pregame)))

        # If you are the first player to join the game, then start the lobby timeout loop
        if len(globvars.master_state.pregame) == 1:
            lobby_timeout.start()

        await botutils.add_alive_role(member)
async def after_lobby_timeout():
    """After lobby timeout"""
    import globvars
    # Only send the lobby timeout message if someone is still in the game
    if not lobby_timeout.is_being_cancelled():
        await botutils.send_lobby(lobby_timeout_str.format(botutils.make_role_ping(ALIVE_ROLE_ID)))
    # Remove the alive role from everyone
    await botutils.remove_all_alive_roles_pregame()
    # Clear the master pregame state
    globvars.master_state.pregame.clear()
    botutils.update_state_machine()
Example #9
0
    async def fleave(self, ctx, *members: Union[discord.Member, str]):
        """Force leave command"""

        import globvars

        if members[0] == "all":
            count = len(globvars.master_state.pregame) - 1
            for player in globvars.master_state.pregame:
                fetched_member = globvars.client.get_guild(
                    SERVER_ID).get_member(player)
                await ctx.send(
                    fleave_str.format(
                        (fetched_member.name if fetched_member else player),
                        count))
                if fetched_member:
                    await botutils.remove_alive_role(fetched_member)
                count -= 1
            globvars.master_state.pregame.clear()
            lobby_timeout.cancel()
            if start_votes_timer.is_running():
                start_votes_timer.cancel()
            botutils.update_state_machine()
        elif isinstance(members[0], discord.Member):
            for member in members:
                # The player has joined; make them leave
                if globvars.master_state.pregame.is_joined(member.id):
                    globvars.master_state.pregame.safe_remove_player(member.id)
                    await ctx.send(
                        fleave_str.format(member.name,
                                          len(globvars.master_state.pregame)))
                    botutils.update_state_machine()
                    # If you are the last player to leave, then cancel the lobby timeout loop
                    if len(globvars.master_state.pregame) == 0:
                        lobby_timeout.cancel()
                    # If the player has voted to start, then remove the start vote
                    if member.id in globvars.start_votes:
                        globvars.start_votes.remove(member.id)
                    # Cancel the start clear timer if no one has voted to start
                    if len(globvars.start_votes
                           ) == 0 and start_votes_timer.is_running():
                        start_votes_timer.cancel()

                # The player has not joined
                else:
                    await ctx.send(
                        fleaved_str.format(ctx.author.mention, member.name))

                await botutils.remove_alive_role(member)
Example #10
0
    async def fjoin(self, ctx, *members: Union[discord.Member, discord.User,
                                               str]):
        """Force join command"""

        import globvars

        game = botutils.GameChooser().get_selected_game()

        for member in members:
            if isinstance(member, str):
                member = botutils.get_member_from_string(member)
                if member is None:
                    continue

            # The player is a bot
            if member.bot:
                await ctx.send(cant_fjoin_bot.format(ctx.author.mention))
                return

            # Too many players
            if len(globvars.master_state.pregame) >= game.MAX_PLAYERS:
                msg = fjoin_max.format(ctx.author.mention,
                                       botutils.BotEmoji.x_emoji, str(game),
                                       game.MAX_PLAYERS)
                await ctx.send(msg)
                return

            # The player has already joined
            if globvars.master_state.pregame.is_joined(member.id):
                await ctx.send(
                    fjoined_str.format(ctx.author.mention, member.name))

            # The player has not yet joined. Make them join.
            else:
                globvars.master_state.pregame.safe_add_player(member.id)
                botutils.update_state_machine()
                await ctx.send(
                    fjoin_str.format(member.name,
                                     len(globvars.master_state.pregame)))

            # If you are the first player to join the game, then start the lobby timeout loop
            if len(globvars.master_state.pregame) == 1:
                lobby_timeout.start()

            await botutils.add_alive_role(member)
Example #11
0
    async def join(self, ctx):
        """Join command"""
        
        import globvars

        # The command user has already joined
        if globvars.master_state.pregame.is_joined(ctx.author.id):
            await ctx.send(joined_str.format(ctx.author.mention))

        # The command user has not joined yet; make them join
        else:
            globvars.master_state.pregame.safe_add_player(ctx.author.id)
            botutils.update_state_machine()
            join_replies = language["doc"]["join"]["outputs"]
            join_weights = language["doc"]["join"]["weights"]

            if join_weights:
                join_reply = random.choices(
                    join_replies,
                    weights=join_weights
                )
                join_str = join_reply[0]
            else:
                join_str = random.choice(join_replies)

            emoji = random.choice(emojis)
            msg = emoji
            msg += " "
            msg += join_str.format(
                ctx.author.name,
                len(globvars.master_state.pregame),
                "player" if len(globvars.master_state.pregame) == 1 else "players"
            )
            await ctx.send(msg)

            # If you are the first player to join the game, then start the lobby timeout loop
            if len(globvars.master_state.pregame) == 1:
                lobby_timeout.start()

        # Still give everyone the role just in case of discord sync issue
        await botutils.add_alive_role(ctx.author)
Example #12
0
    async def fleave(self, ctx, *, member: discord.Member):
        """Force leave command"""

        import globvars

        # The player has joined; make them leave.
        if globvars.master_state.pregame.is_joined(member.id):
            globvars.master_state.pregame.safe_remove_player(member.id)
            await ctx.send(
                fleave_str.format(member.name,
                                  len(globvars.master_state.pregame)))
            botutils.update_state_machine()
            # If you are the last player to leave, then cancel the lobby timeout loop
            if len(globvars.master_state.pregame) == 0:
                lobby_timeout.cancel()

        # The player has not joined.
        else:
            await ctx.send(fleaved_str.format(ctx.author.mention, member.name))

        await botutils.remove_alive_role(member)
    async def quit(self, ctx):
        """Quit command"""

        import globvars

        # The command user has joined; make them quit
        if globvars.master_state.pregame.is_joined(ctx.author.id):
            globvars.master_state.pregame.safe_remove_player(ctx.author.id)
            botutils.update_state_machine()
            await ctx.send(
                quit_str.format(ctx.author.name,
                                len(globvars.master_state.pregame)))
            # If you are the last player to leave, then cancel the lobby timeout loop
            if len(globvars.master_state.pregame) == 0:
                lobby_timeout.cancel()

        # The command user has not joined
        else:
            await ctx.send(quitted_str.format(ctx.author.mention))

        # Still take away the role from everyone just in case of discord sync issue
        await botutils.remove_alive_role(ctx.author)
Example #14
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))
Example #15
0
    async def join(self, ctx):
        """Join command"""

        import globvars

        if globvars.master_state.game:
            # This check is to ensure a player doesn't join right after !start
            # before the game is fully set up and end up breaking the game.
            return

        # The command user has already joined
        if globvars.master_state.pregame.is_joined(ctx.author.id):
            await ctx.send(joined_str.format(ctx.author.mention))

        # The command user has not joined yet; make them join
        else:
            user_ids = set()

            with sqlite3.connect("data.sqlite3") as conn:
                c = conn.cursor()

                c.execute(
                    """
                SELECT
                    primary_user_id,
                    secondary_user_id
                FROM
                    player_map
                WHERE
                    primary_user_id = :user_id
                    OR secondary_user_id = :user_id
                """, {
                        "user_id": ctx.author.id,
                    })

                for row in c.fetchall():
                    primary, secondary = row

                    user_ids.add(primary)
                    user_ids.add(secondary)

            for user_id in globvars.master_state.pregame:
                if user_id in user_ids:
                    user = globvars.client.get_user(user_id)
                    await ctx.send(
                        joined_alt_str.format(ctx.author.mention, str(user)))
                    return

            globvars.master_state.pregame.safe_add_player(ctx.author.id)
            botutils.update_state_machine()
            join_replies = bot_text["doc"]["join"]["outputs"]
            join_weights = bot_text["doc"]["join"]["weights"]

            if join_weights:
                join_reply = random.choices(join_replies, weights=join_weights)
                join_str = join_reply[0]
            else:
                join_str = random.choice(join_replies)

            emoji = random.choice(emojis)
            msg = emoji
            msg += " "
            msg += join_str.format(
                ctx.author.name, len(globvars.master_state.pregame), "player"
                if len(globvars.master_state.pregame) == 1 else "players")
            await ctx.send(msg)

            # If you are the first player to join the game, then start the lobby timeout loop
            if len(globvars.master_state.pregame) == 1:
                if lobby_timeout.is_running():
                    lobby_timeout.cancel()
                lobby_timeout.start()

        # Still give everyone the role just in case of discord sync issue
        await botutils.add_alive_role(ctx.author)