Exemple #1
0
 def get_n_policies(self, n=5):
     # for now just get n random policies
     policies = list(self.get_policies())
     if not policies:
         return []
     random.shuffle(policies)
     return policies[:n]
Exemple #2
0
    def shuffle(self):
        if not hasattr(self, "shuffle_attributes"):
            return

        for attributes in sorted(self.shuffle_attributes):
            if len(attributes) == 1:
                attribute = attributes[0]
                value = sorted(getattr(self, attribute))
                random.shuffle(value)
                setattr(self, attribute, value)
                continue
            values = [getattr(self, attribute) for attribute in attributes]
            random.shuffle(values)
            for attribute, value in zip(attributes, values):
                setattr(self, attribute, value)
Exemple #3
0
def force_role(self, role_to_force: Role):
    # Make sure a role is to be played, force it otherwise
    # Warning: This can replace previously forced role
    if role_to_force in self.available_roles:
        return
    else:
        idx = 0  # Let's replace the first role in self.available_roles
        if role_to_force in self.extra_roles:
            # Get it by swapping with self.extra_roles's
            swap_idx = self.extra_roles.index(role_to_force)
            self.available_roles[idx], self.extra_roles[swap_idx] = (
                self.extra_roles[swap_idx],
                self.available_roles[idx],
            )
        else:
            # Or just force it manually
            self.available_roles[idx] = role_to_force
    return random.shuffle(self.available_roles), random.shuffle(self.extra_roles)
Exemple #4
0
    def groupshuffle(cls):
        if (not hasattr(cls, "groupshuffle_enabled")
                or not cls.groupshuffle_enabled):
            return

        shuffled = range(cls.numgroups)
        random.shuffle(shuffled)
        swapdict = {}
        for a, b in zip(range(cls.numgroups), shuffled):
            a = cls.getgroup(a)
            b = cls.getgroup(b)
            for a1, b1 in zip(a, b):
                swapdict[a1] = (b1.groupindex, b1.index, b1.pointer)

        for o in cls.every:
            groupindex, index, pointer = swapdict[o]
            o.groupindex = groupindex
            o.index = index
            o.pointer = pointer
Exemple #5
0
    def intershuffle(cls):
        if not hasattr(cls, "intershuffle_attributes"):
            return

        hard_shuffle = False
        if (len(set([o.rank for o in cls.every])) == 1
                or all([o.rank == o.index for o in cls.every])):
            hard_shuffle = True

        for attributes in cls.intershuffle_attributes:
            candidates = [o for o in cls.every
                          if o.rank >= 0 and o.intershuffle_valid]
            if hard_shuffle:
                shuffled = list(candidates)
                random.shuffle(shuffled)
            else:
                candidates = sorted(candidates, key=lambda c: c.rank)
                shuffled = list(candidates)
                max_index = len(candidates)-1
                done = set([])
                for i, o in enumerate(candidates):
                    new_index = i
                    if shuffled[i] in done:
                        continue
                    while random.choice([True, False]):
                        new_index += min(1, (max_index / 10.0))
                    new_index = int(round(new_index))
                    new_index = min(new_index, max_index)
                    a, b = shuffled[i], shuffled[new_index]
                    done.add(a)
                    shuffled[i] = b
                    shuffled[new_index] = a

            if isinstance(attributes, str) or isinstance(attributes, unicode):
                attributes = [attributes]

            for attribute in attributes:
                swaps = []
                for a, b in zip(candidates, shuffled):
                    aval, bval = getattr(a, attribute), getattr(b, attribute)
                    swaps.append(bval)
                for a, bval in zip(candidates, swaps):
                    setattr(a, attribute, bval)
Exemple #6
0
 async def get_response(self, ctx, question):
     entries = [question["correct_answer"]] + question["incorrect_answers"]
     entries = random.shuffle(entries)
     answer = await self.bot.paginator.Choose(
         entries=entries,
         title=question["question"],
         footer=(f"Difficulty: {question['difficulty']} | Category:"
                 f" {question['category']}"),
         timeout=15,
     ).paginate(ctx)
     return answer == question["correct_answer"]
Exemple #7
0
 async def send_cast(self):
     cast = copy.copy(self.players)
     cast = random.shuffle(cast)
     cast = list(chunks(cast, 2))
     self.cast = cast
     text = _("Team")
     paginator = commands.Paginator(prefix="", suffix="")
     paginator.add_line(_("**The cast**"))
     for i, team in enumerate(cast, start=1):
         if len(team) == 2:
             paginator.add_line(
                 f"{text} #{i}: {team[0].mention} {team[1].mention}")
         else:
             paginator.add_line(f"{text} #{i}: {team[0].mention}")
     for page in paginator.pages:
         await self.ctx.send(page)
Exemple #8
0
 def prepare_deck(self):
     self.deck = []
     for colour in ["hearts", "diamonds", "spades", "clubs"]:
         for value in range(2, 15):  # 11 = Jack, 12 = Queen, 13 = King, 14 = Ace
             if value == 11:
                 card = "j"
             elif value == 12:
                 card = "q"
             elif value == 13:
                 card = "k"
             elif value == 14:
                 card = "a"
             else:
                 card = str(value)
             self.deck.append((value, colour, self.cards[f"{card}{colour}"]))
     self.deck = self.deck * 6  # BlackJack is played with 6 sets of cards
     self.deck = random.shuffle(self.deck)
Exemple #9
0
def get_roles(number_of_players: int) -> List[Role]:
    number_of_players += 2  # Thief is in play
    if number_of_players > len(ROLES_FOR_PLAYERS):
        roles = ROLES_FOR_PLAYERS
        # Fill up with villagers and wolves as all special roles are taken
        for i in range(number_of_players - len(roles)):
            if i % 2 == 0:
                roles.append(Role.WEREWOLF)
            else:
                roles.append(Role.VILLAGER)
    else:
        roles = ROLES_FOR_PLAYERS[:number_of_players]
    if sum(1 for role in roles if role == Role.SISTER) == 1:
        for idx, role in enumerate(roles):
            if role == Role.SISTER:
                roles[idx] = Role.VILLAGER
    if sum(1 for role in roles if role == Role.BROTHER) < 3:
        for idx, role in enumerate(roles):
            if role == Role.BROTHER:
                roles[idx] = Role.VILLAGER
    roles = random.shuffle(roles)
    return roles
Exemple #10
0
                            user=u.mention))
        toremove = 2**math.floor(math.log2(len(participants)))
        if toremove != len(participants):
            await ctx.send(
                _("There are **{num}** entries, due to the fact we need a playable"
                  " tournament, the last **{removed}** have been removed.").
                format(num=len(participants),
                       removed=len(participants) - toremove))
            participants = participants[:-(len(participants) - toremove)]
        else:
            await ctx.send(
                _("Tournament started with **{num}** entries.").format(
                    num=toremove))
        text = _("vs")
        while len(participants) > 1:
            participants = random.shuffle(participants)
            matches = list(chunks(participants, 2))

            for match in matches:
                await ctx.send(f"{match[0].mention} {text} {match[1].mention}")
                await asyncio.sleep(2)
                async with self.bot.pool.acquire() as conn:
                    val1 = sum(await self.bot.get_damage_armor_for(
                        match[0], conn=conn)) + random.randint(1, 7)
                    val2 = sum(await self.bot.get_damage_armor_for(
                        match[1], conn=conn)) + random.randint(1, 7)
                if val1 > val2:
                    winner = match[0]
                    looser = match[1]
                elif val2 > val1:
                    winner = match[1]
Exemple #11
0
    async def werewolf(
        self,
        ctx,
        mode: Optional[WerewolfMode] = "Classic",
        speed: str.title = "Normal",
        min_players: IntGreaterThan(1) = None,
    ):
        _("""
            `[mode]` - The mode to play, see below for available options. (optional and defaults to Classic)
            `[speed]` - The game speed to play, see below available options. (optional and defaults to Normal)
            `[min_players]` - The minimum players needed to play. (optional and defaults depending on the game mode: Classic: 5, Imbalanced: 5, Huntergame: 8, Villagergame: 5, Valentines: 8, IdleRPG: 5)

            Starts a game of Werewolf. Find the werewolves, before they find you!
            Your goal to win is indicated on the role you have.
            **Game modes:** `Classic` (default), `Imbalanced`, `Huntergame`, `Villagergame`, `Valentines`, `IdleRPG`. Use `{prefix}ww modes` for detailed info.
            **Game speeds** (in seconds): `Normal`: 60 (default), `Extended`: 90, `Fast`: 45, `Blitz`: 30. Use `{prefix}ww speeds` for detailed info.
            **Aliases:**
            `ww`
            **Examples:**
            `{prefix}ww Blitz` for Classic mode on Blitz speed
            `{prefix}ww Imbalanced` for Imbalanced mode on Normal speed
            `{prefix}ww Valentines Extended` for Valentines mode on Extended speed
            `{prefix}ww Huntergame Fast` for Huntergame mode on Fast speed
            """)
        # TODO:
        # Bizarro: Roles are flipped.
        # Random: Roles are reassigned randomly every night.
        # Zombie (Classic-based, another team) - There's a chance that a random player will be randomly resurrected as Zombie and they can devour any villagers or werewolves with the other zombies.
        if self.games.get(ctx.channel.id):
            return await ctx.send(_("There is already a game in here!"))
        game_modes = [
            "Classic",
            "Imbalanced",
            "Huntergame",
            "Villagergame",
            "Valentines",
            "Idlerpg",
        ]
        if mode not in game_modes:
            return await ctx.send(
                _("Invalid game mode. Use `{prefix}help ww` to get help on this"
                  " command.").format(prefix=ctx.prefix))
        elif mode == "Idlerpg":
            mode = "IdleRPG"
        game_speeds = ["Normal", "Extended", "Fast", "Blitz"]
        if speed not in game_speeds:
            return await ctx.send(
                _("Invalid game speed. Use `{prefix}help ww` to get help on this"
                  " command.").format(prefix=ctx.prefix))
        minimum_players = {
            "Classic": 5,
            "Imbalanced": 5,
            "Huntergame": 8,
            "Villagergame": 5,
            "Valentines": 8,
            "IdleRPG": 5,
        }
        if not min_players:
            default_min_players = (
                5  # Get default of Classic mode if unexpected value happened
            )
            min_players = minimum_players.get(mode, default_min_players)
        self.games[ctx.channel.id] = "forming"
        additional_text = _(
            "Use `{prefix}help ww` to get help on werewolf commands. Use `{prefix}ww"
            " roles` to view descriptions of game roles and their goals to win. Use"
            " `{prefix}ww modes` and `{prefix}ww speeds` to see info about available"
            " game modes and speeds.").format(prefix=ctx.prefix)
        mode_emojis = {"Huntergame": "🔫", "Valentines": "💕"}
        mode_emoji = mode_emojis.get(mode, "")
        if ctx.channel.id == self.bot.config.official_tournament_channel_id:
            # TODO: Determine threshold players when wolves can kill 2 villagers per night in mass-games
            id_ = await self.bot.start_joins()
            url = f"https://join.idlerpg.xyz/{id_}"
            text = _(
                "**{author} started a mass-game of Werewolf!**\n**{mode}** mode on"
                " **{speed}** speed. Go to {url} to join in the next 10 minutes."
                " **Minimum of {min_players} players are required.**")
            try:
                await ctx.send(embed=discord.Embed(
                    title=_("Werewolf Mass-game!"),
                    description=text.format(
                        author=ctx.author.mention,
                        mode=mode_emoji + mode,
                        speed=speed,
                        url=url,
                        min_players=min_players,
                    ),
                    url=url,
                    colour=self.bot.config.primary_colour,
                ).set_author(
                    name=str(ctx.author),
                    icon_url=ctx.author.avatar_url_as(size=64)).add_field(
                        name=_("New to Werewolf?"), value=additional_text))
            except discord.errors.Forbidden:
                del self.games[ctx.channel.id]
                return await ctx.send(
                    _("An error happened during the Werewolf. Missing Permission:"
                      " `Embed Links` . Please check the **Edit Channel >"
                      " Permissions** and **Server Settings > Roles** then try again!"
                      ))
            await asyncio.sleep(60 * 10)
            players = await self.bot.get_joins(id_)
        else:
            title = _("Werewolf game!")
            text = _(
                "**{author} started a game of Werewolf!**\n**{mode}** mode on"
                " **{speed}** speed. React with 🐺 to join the game! **Minimum of"
                " {min_players} players are required. Starting in 30 seconds.\n{num}"
                " joined**")
            players = [ctx.author]
            try:
                msg = await ctx.send(embed=discord.Embed(
                    title=title,
                    description=text.format(
                        author=ctx.author.mention,
                        mode=mode_emoji + mode,
                        speed=speed,
                        min_players=min_players,
                        num=len(players),
                    ),
                    colour=self.bot.config.primary_colour,
                ).set_author(
                    name=str(ctx.author),
                    icon_url=ctx.author.avatar_url_as(size=64)).add_field(
                        name=_("New to Werewolf?"), value=additional_text))
                await msg.add_reaction("\U0001f43a")
            except discord.errors.Forbidden:
                del self.games[ctx.channel.id]
                return await ctx.send(
                    _("An error happened during the Werewolf. Missing Permission:"
                      " `Embed Links` . Please check the **Edit Channel >"
                      " Permissions** and **Server Settings > Roles** then try again!"
                      ))

            def check(reaction, user):
                return (user not in players and reaction.message.id == msg.id
                        and reaction.emoji == "\U0001f43a" and not user.bot)

            while True:
                try:
                    reaction, user = await self.bot.wait_for("reaction_add",
                                                             check=check,
                                                             timeout=30)
                except asyncio.TimeoutError:
                    break
                players.append(user)
                await msg.edit(embed=discord.Embed(
                    title=title,
                    description=text.format(
                        author=ctx.author.mention,
                        mode=mode_emoji + mode,
                        speed=speed,
                        min_players=min_players,
                        num=len(players),
                    ),
                    colour=self.bot.config.primary_colour,
                ).set_author(
                    name=str(ctx.author),
                    icon_url=ctx.author.avatar_url_as(size=64)).add_field(
                        name=_("New to Werewolf?"), value=additional_text))

            # Check for not included participants
            try:
                msg = await ctx.channel.fetch_message(msg.id)
                for reaction in msg.reactions:
                    if reaction.emoji == "\U0001f43a":
                        async for user in reaction.users():
                            if user != ctx.me and user not in players:
                                players.append(user)
                        break
            except discord.errors.NotFound:
                del self.games[ctx.channel.id]
                await ctx.send(
                    _("An error happened during the Werewolf. Please try again!"
                      ))
                return

        if len(players) < min_players:
            del self.games[ctx.channel.id]
            await self.bot.reset_cooldown(ctx)
            return await ctx.send(
                _("Not enough players joined... We didn't reach the minimum"
                  " {min_players} players. 🙁").format(min_players=min_players))

        players = random.shuffle(players)
        try:
            game = Game(ctx, players, mode, speed)
            self.games[ctx.channel.id] = game
            await game.run()
        except Exception as e:
            await ctx.send(
                _("An error happened during the Werewolf. Please try again!"))
            del self.games[ctx.channel.id]
            raise e
        try:
            del self.games[ctx.channel.id]
        except KeyError:  # got stuck in between
            pass
Exemple #12
0
    async def werewolf(
        self,
        ctx,
        mode: WerewolfMode | None = "Classic",
        speed: str.title = "Normal",
        min_players: IntGreaterThan(1) = None,
    ):
        _("""
            `[mode]` - The mode to play, see below for available options. (optional and defaults to Classic)
            `[speed]` - The game speed to play, see below available options. (optional and defaults to Normal)
            `[min_players]` - The minimum players needed to play. (optional and defaults depending on the game mode: Classic: 5, Imbalanced: 5, Huntergame: 8, Villagergame: 5, Valentines: 8, IdleRPG: 5)

            Starts a game of Werewolf. Find the werewolves, before they find you!
            Your goal to win is indicated on the role you have.
            **Game modes:** `Classic` (default), `Imbalanced`, `Huntergame`, `Villagergame`, `Valentines`, `IdleRPG`. Use `{prefix}ww modes` for detailed info.
            **Game speeds** (in seconds): `Normal`: 60 (default), `Extended`: 90, `Fast`: 45, `Blitz`: 30. Use `{prefix}ww speeds` for detailed info.
            **Aliases:**
            `ww`
            **Examples:**
            `{prefix}ww Blitz` for Classic mode on Blitz speed
            `{prefix}ww Imbalanced` for Imbalanced mode on Normal speed
            `{prefix}ww Valentines Extended` for Valentines mode on Extended speed
            `{prefix}ww Huntergame Fast` for Huntergame mode on Fast speed
            """)

        # TODO:
        # Bizarro: Roles are flipped.
        # Random: Roles are reassigned randomly every night.
        # Zombie (Classic-based, another team) - There's a chance that a random player will be randomly resurrected as Zombie and they can devour any villagers or werewolves with the other zombies.

        if self.games.get(ctx.channel.id):
            return await ctx.send(_("There is already a game in here!"))

        game_modes = [
            "Classic",
            "Imbalanced",
            "Huntergame",
            "Villagergame",
            "Valentines",
            "Idlerpg",
        ]

        minimum_players = {
            "Classic": 5,
            "Imbalanced": 5,
            "Huntergame": 8,
            "Villagergame": 5,
            "Valentines": 8,
            "IdleRPG": 5,
        }

        game_speeds = ["Normal", "Extended", "Fast", "Blitz"]

        if mode not in game_modes:
            return await ctx.send(
                _("Invalid game mode. Use `{prefix}help ww` to get help on this"
                  " command.").format(prefix=ctx.prefix))
        elif mode == "Idlerpg":
            mode = "IdleRPG"

        if speed not in game_speeds:
            return await ctx.send(
                _("Invalid game speed. Use `{prefix}help ww` to get help on this"
                  " command.").format(prefix=ctx.prefix))

        if not min_players:
            # Get default of Classic mode if unexpected value happened
            min_players = minimum_players.get(mode, 5)

        self.games[ctx.channel.id] = "forming"

        additional_text = _(
            "Use `{prefix}help ww` to get help on werewolf commands. Use `{prefix}ww"
            " roles` to view descriptions of game roles and their goals to win. Use"
            " `{prefix}ww modes` and `{prefix}ww speeds` to see info about available"
            " game modes and speeds.").format(prefix=ctx.prefix)

        mode_emojis = {"Huntergame": "🔫", "Valentines": "💕"}
        mode_emoji = mode_emojis.get(mode, "")

        if (self.bot.config.game.official_tournament_channel_id
                and ctx.channel.id
                == self.bot.config.game.official_tournament_channel_id):
            # TODO: Determine threshold players when wolves can kill 2 villagers per night in mass-games
            view = JoinView(
                Button(style=ButtonStyle.primary,
                       label=_("Join the Werewolf game!")),
                message=_("You joined the Werewolf game."),
                timeout=60 * 10,
            )
            text = _(
                "**{author} started a mass-game of Werewolf!**\n**{mode}** mode on"
                " **{speed}** speed. You can join in the next 10 minutes."
                " **Minimum of {min_players} players are required.**")

            await ctx.send(
                embed=discord.Embed(
                    title=_("Werewolf Mass-game!"),
                    description=text.format(
                        author=ctx.author.mention,
                        mode=mode_emoji + mode,
                        speed=speed,
                        min_players=min_players,
                    ),
                    colour=self.bot.config.game.primary_colour,
                ).set_author(name=str(ctx.author),
                             icon_url=ctx.author.display_avatar.url).add_field(
                                 name=_("New to Werewolf?"),
                                 value=additional_text),
                view=view,
            )

            await asyncio.sleep(60 * 10)

            view.stop()
            players = list(view.joined)
        else:
            view = JoinView(
                Button(style=ButtonStyle.primary,
                       label=_("Join the Werewolf game!")),
                message=_("You joined the Werewolf game."),
                timeout=120,
            )
            view.joined.add(ctx.author)
            title = _("Werewolf game!")
            text = _(
                "**{author} started a game of Werewolf!**\n**{mode}** mode on"
                " **{speed}** speed. Minimum of"
                " **{min_players}** players are required. Starting in 2 minutes."
            )

            try:
                await ctx.send(
                    embed=discord.Embed(
                        title=title,
                        description=text.format(
                            author=ctx.author.mention,
                            mode=mode_emoji + mode,
                            speed=speed,
                            min_players=min_players,
                        ),
                        colour=self.bot.config.game.primary_colour,
                    ).set_author(
                        name=str(ctx.author),
                        icon_url=ctx.author.display_avatar.url).add_field(
                            name=_("New to Werewolf?"), value=additional_text),
                    view=view,
                )
            except discord.errors.Forbidden:
                del self.games[ctx.channel.id]
                return await ctx.send(
                    _("An error happened during the Werewolf. Missing Permission:"
                      " `Embed Links` . Please check the **Edit Channel >"
                      " Permissions** and **Server Settings > Roles** then try again!"
                      ))

            await asyncio.sleep(60 * 2)

            view.stop()
            players = list(view.joined)

        if len(players) < min_players:
            del self.games[ctx.channel.id]
            await self.bot.reset_cooldown(ctx)
            return await ctx.send(
                _("Not enough players joined... We didn't reach the minimum"
                  " {min_players} players. �").format(
                      min_players=min_players))

        players = random.shuffle(players)
        try:
            game = Game(ctx, players, mode, speed)
            self.games[ctx.channel.id] = game
            await game.run()
        except Exception as e:
            await ctx.send(
                _("An error happened during the Werewolf. Please try again!"))
            del self.games[ctx.channel.id]
            raise e

        try:
            del self.games[ctx.channel.id]
        except KeyError:  # got stuck in between
            pass
Exemple #13
0
    async def draw(
        self, ctx, enemy: MemberWithCharacter = None, money: IntGreaterThan(-1) = 0
    ):
        _(
            """`[enemy]` - A user who has a profile; defaults to None
            `[money]` - The bet money. A whole number that can be 0 or greater; defaults to 0

            Draws a random card from the 52 French playing cards. Playing Draw with someone for money is also available if the enemy is mentioned. The player with higher value of the drawn cards will win the bet money.

            This command has no effect on your balance if done with no enemy mentioned.
            (This command has a cooldown of 15 seconds.)"""
        )
        if not enemy:
            return await ctx.send(
                content=f"{ctx.author.mention} you drew:",
                file=discord.File(f"assets/cards/{random.choice(self.cards)}"),
            )
        else:
            if enemy == ctx.author:
                return await ctx.send(_("Please choose someone else."))
            if enemy == ctx.me:
                return await ctx.send(_("You should choose a human to play with you."))

            if ctx.character_data["money"] < money:
                return await ctx.send(_("You are too poor."))

            await self.bot.pool.execute(
                'UPDATE profile SET "money"="money"-$1 WHERE "user"=$2;',
                money,
                ctx.author.id,
            )

            async def money_back():
                await self.bot.pool.execute(
                    'UPDATE profile SET "money"="money"+$1 WHERE "user"=$2;',
                    money,
                    ctx.author.id,
                )
                return await self.bot.reset_cooldown(ctx)

            try:
                if not await ctx.confirm(
                    _(
                        "{author} challenges {enemy} to a game of Draw for"
                        " **${money}**. Do you accept?"
                    ).format(
                        author=ctx.author.mention,
                        enemy=enemy.mention,
                        money=money,
                    ),
                    user=enemy,
                    timeout=15,
                ):
                    await money_back()
                    return await ctx.send(
                        _(
                            "They declined. They don't want to play a game of Draw with"
                            " you {author}."
                        ).format(author=ctx.author.mention)
                    )
            except self.bot.paginator.NoChoice:
                await money_back()
                return await ctx.send(
                    _(
                        "They didn't choose anything. It seems they're not interested"
                        " to play a game of Draw with you {author}."
                    ).format(author=ctx.author.mention)
                )

            if not await has_money(self.bot, enemy.id, money):
                await money_back()
                return await ctx.send(
                    _("{enemy} You don't have enough money to play.").format(
                        enemy=enemy.mention
                    )
                )

            await self.bot.pool.execute(
                'UPDATE profile SET "money"="money"-$1 WHERE "user"=$2;',
                money,
                enemy.id,
            )

            cards = self.cards.copy()
            cards = random.shuffle(cards)
            rank_values = {
                "jack": 11,
                "queen": 12,
                "king": 13,
                "ace": 14,
            }

            while True:
                try:
                    author_card = cards.pop()
                    enemy_card = cards.pop()
                except IndexError:
                    return await ctx.send(
                        _(
                            "Cards ran out. This is a very rare issue that could mean"
                            " image files for cards have become insufficient. Please"
                            " report this issue to the bot developers."
                        )
                    )

                rank1 = author_card[: author_card.find("_")]
                rank2 = enemy_card[: enemy_card.find("_")]
                drawn_values = [
                    int(rank_values.get(rank1, rank1)),
                    int(rank_values.get(rank2, rank2)),
                ]

                async with self.bot.pool.acquire() as conn:
                    if drawn_values[0] == drawn_values[1]:
                        await conn.execute(
                            'UPDATE profile SET "money"="money"+$1 WHERE "user"=$2 OR'
                            ' "user"=$3;',
                            money,
                            ctx.author.id,
                            enemy.id,
                        )
                        text = _("Nobody won. {author} and {enemy} tied.").format(
                            author=ctx.author.mention,
                            enemy=enemy.mention,
                        )
                    else:
                        players = [ctx.author, enemy]
                        winner = players[drawn_values.index(max(drawn_values))]
                        loser = players[players.index(winner) - 1]
                        await conn.execute(
                            'UPDATE profile SET "money"="money"+$1 WHERE "user"=$2;',
                            money * 2,
                            winner.id,
                        )
                        await self.bot.log_transaction(
                            ctx,
                            from_=loser.id,
                            to=winner.id,
                            subject="gambling",
                            data={"Amount": money},
                            conn=conn,
                        )
                        text = _(
                            "{winner} won the Draw vs {loser}! Congratulations!"
                        ).format(winner=winner.mention, loser=loser.mention)

                await ctx.send(
                    content=(
                        _("{author}, while playing against {enemy}, you drew:").format(
                            author=ctx.author.mention, enemy=enemy.mention
                        )
                    ),
                    file=discord.File(f"assets/cards/{author_card}"),
                )
                await ctx.send(
                    content=(
                        _("{enemy}, while playing against {author}, you drew:").format(
                            enemy=enemy.mention, author=ctx.author.mention
                        )
                    ),
                    file=discord.File(f"assets/cards/{enemy_card}"),
                )
                await ctx.send(text)

                if drawn_values[0] != drawn_values[1]:
                    break
                else:
                    msg = await ctx.send(
                        content=f"{ctx.author.mention}, {enemy.mention}",
                        embed=discord.Embed(
                            title=_("Break the tie?"),
                            description=_(
                                "{author}, {enemy} You tied. Do you want to break the"
                                " tie by playing again for **${money}**?"
                            ).format(
                                author=ctx.author.mention,
                                enemy=enemy.mention,
                                money=money,
                            ),
                            colour=discord.Colour.blurple(),
                        ),
                    )

                    emoji_no = "\U0000274e"
                    emoji_yes = "\U00002705"
                    emojis = (emoji_no, emoji_yes)

                    for emoji in emojis:
                        await msg.add_reaction(emoji)

                    def check(r, u):
                        return (
                            str(r.emoji) in emojis
                            and r.message.id == msg.id
                            and u in [ctx.author, enemy]
                            and not u.bot
                        )

                    async def cleanup() -> None:
                        with suppress(discord.HTTPException):
                            await msg.delete()

                    accept_redraws = {}

                    while len(accept_redraws) < 2:
                        try:
                            reaction, user = await self.bot.wait_for(
                                "reaction_add", timeout=15, check=check
                            )
                        except asyncio.TimeoutError:
                            await cleanup()
                            return await ctx.send(
                                _("One of you or both didn't react on time.")
                            )
                        else:
                            if not (accept := bool(emojis.index(str(reaction.emoji)))):
                                await cleanup()
                                return await ctx.send(
                                    _("{user} declined to break the tie.").format(
                                        user=user.mention
                                    )
                                )
                            if user.id not in accept_redraws:
                                accept_redraws[user.id] = accept

                    await cleanup()

                    if not await has_money(self.bot, ctx.author.id, money):
                        return await ctx.send(
                            _("{author} You don't have enough money to play.").format(
                                author=ctx.author.mention
                            )
                        )
                    if not await has_money(self.bot, enemy.id, money):
                        return await ctx.send(
                            _("{enemy} You don't have enough money to play.").format(
                                enemy=enemy.mention
                            )
                        )

                    await self.bot.pool.execute(
                        'UPDATE profile SET "money"="money"-$1 WHERE "user"=$2 OR'
                        ' "user"=$3;',
                        money,
                        ctx.author.id,
                        enemy.id,
                    )
    def generate(self,
                 pos,
                 good_enough=None,
                 tries_limit=None,
                 subgroup=None,
                 basis=None):
        """Generate the parameters by finding good polynomials and building the parameters
        according to Proposition 8 & Remark 5 of [GW15].
        @pos - the reconstruction pos
        @good_enough - amount of subfield elements sent which is good enough for us.
                       if unset - the information theoretic best is taken (which might be impossible) 
        @tries_limit - amount of polynomial sets to try. If unset - number of tries is unlimited
        @subgroup - amount of points to randomly checks before calculating the bandwidth of the scheme
        @basis - optional specific basis of gf over subfield to use
        """
        pts = [p for p in self._pts]
        if pos not in pts:
            pts.append(pos)
        n = len(pts)
        t = self._t
        ext = self._gf.get_extension()

        # Set good enough to the lower bound of information needed - at least t parties, at least one element (in the big field)
        if good_enough is None:
            good_enough = -1
        good_enough = max(good_enough, t, ext)

        if tries_limit is None:
            tries_limit = -1

        # Set subgroup size for testing bandwidth
        # Only if bandwidth on subgroup seems to be better than current bandwidth we continue
        if subgroup is None:
            subgroup_fraction, subgroup_min = Config.GW_PARAMS_SUBGROUP_SIZE
            subgroup = int(ceil(n / subgroup_fraction))
            subgroup = max(subgroup, subgroup_min)
        subgroup = min(n - 1, subgroup)
        subgroup_factor = float(subgroup) / n

        # Choose our polynomials so their evaluation in @pos will be some predefined base
        # We don't care about this degree of freedom - as it only changes our polynomial by a multiplicative scalar factor
        if basis is not None:
            assert len(basis) == ext, "Invalid size of basis supplied"
            assert self._linear_independant(basis), "Invalid basis supplied"
        else:
            # Choose the monomial basis as default
            subf = self._gf.get_subfield()
            gf_x = self._gf([subf.zero(), subf.one()])
            basis = [x for x in powers(gf_x, ext)]

        pol_deg = n - t - 2
        best_bandwidth = (n * ext) + 1  # <- More than the worst case bandwidth
        best_subgroup_bandwidth = int(ceil(subgroup_factor * best_bandwidth))
        shuffled_pts = [p for p in pts]
        best_pols = None
        done = False
        try_i = 0
        try:
            while not done and try_i != tries_limit:
                try_i += 1

                # Choose a random polynomials with a sample of the points as roots,
                # while still making sure the evaluation in `pos` will yield the `basis`
                pols = []
                for b in basis:
                    roots = random.sample(
                        pts,
                        pol_deg + 1)  # Over sample by 1 in case @pos gets in
                    try:
                        roots.remove(pos)
                    except ValueError:
                        roots.pop(-1)  # Remove someone else (arbitrary)
                    pol = LinearFactors(self._gf, roots, constraint=(pos, b))
                    pols.append(pol)

                # Sum the degree of the vector spaces spanned by {p(pt) | p in pols} for each pt (except pos)
                # First start with `subgroup` random points and see if
                random.shuffle(shuffled_pts)
                pts_iter = iter(shuffled_pts)
                bandwidth = 0
                for i in xrange(subgroup):
                    pt = pts_iter.next()
                    if pt == pos:
                        pt = pts_iter.next()
                    bandwidth += self._degree(pol(pt) for pol in pols)

                if bandwidth > best_subgroup_bandwidth:
                    continue
                #else:
                bandwidth += sum(
                    self._degree(pol(pt) for pol in pols) for pt in pts_iter
                    if pt != pos)

                if bandwidth < best_bandwidth:
                    best_pols = pols
                    best_bandwidth = bandwidth
                    best_subgroup_bandwidth = int(
                        ceil(subgroup_factor * best_bandwidth))
                    log.info("Found scheme with %d bandwidth (%d%%)",
                             best_bandwidth,
                             int(ceil((100.0 * best_bandwidth) / (ext * n))))
                    if bandwidth <= good_enough:
                        done = True

        except KeyboardInterrupt:
            if best_pols is None:
                raise
            # Else - continue normally

        basis_elements = map(
            lambda pol: -pol(pos), best_pols
        )  #Notice: Negation added for correct result (mistake in [GW15] ?)
        dual = self._dual_basis(basis_elements)
        mus, mus_basis = self._calc_mus(pos, pts, best_pols)

        return dual, mus, mus_basis, best_bandwidth