aboutsummaryrefslogtreecommitdiffstats
path: root/bot/exts/fun/anagram.py
blob: d8ea6a554e8517f1154309e90a8f86ca1f64f9f5 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import asyncio
import json
import logging
import random
from pathlib import Path

import discord
from discord.ext import commands

from bot.bot import Bot
from bot.constants import Colours

log = logging.getLogger(__name__)

TIME_LIMIT = 60

# anagram.json file contains all the anagrams
with open(Path("bot/resources/fun/anagram.json"), "r") as f:
    ANAGRAMS_ALL = json.load(f)


class AnagramGame:
    """
    Used for creating instances of anagram games.

    Once multiple games can be run at the same time, this class' instances
    can be used for keeping track of each anagram game.
    """

    def __init__(self, scrambled: str, correct: list[str]) -> None:
        self.scrambled = scrambled
        self.correct = set(correct)

        self.winners = set()

    async def message_creation(self, message: discord.Message) -> None:
        """Check if the message is a correct answer and remove it from the list of answers."""
        if message.content.lower() in self.correct:
            self.winners.add(message.author.mention)
            self.correct.remove(message.content.lower())


class Anagram(commands.Cog):
    """Cog for the Anagram game command."""

    def __init__(self, bot: Bot):
        self.bot = bot

        self.games: dict[int, AnagramGame] = {}

    @commands.command(name="anagram", aliases=("anag", "gram", "ag"))
    async def anagram_command(self, ctx: commands.Context) -> None:
        """
        Given shuffled letters, rearrange them into anagrams.

        Show an embed with scrambled letters which if rearranged can form words.
        After a specific amount of time, list the correct answers and whether someone provided a
        correct answer.
        """
        if self.games.get(ctx.channel.id):
            await ctx.send("An anagram is already being solved in this channel!")
            return

        scrambled_letters, correct = random.choice(list(ANAGRAMS_ALL.items()))

        game = AnagramGame(scrambled_letters, correct)
        self.games[ctx.channel.id] = game

        anagram_embed = discord.Embed(
            title=f"Find anagrams from these letters: '{scrambled_letters.upper()}'",
            description=f"You have {TIME_LIMIT} seconds to find correct words.",
            colour=Colours.purple,
        )

        await ctx.send(embed=anagram_embed)
        await asyncio.sleep(TIME_LIMIT)

        if game.winners:
            win_list = ", ".join(game.winners)
            content = f"Well done {win_list} for getting it right!"
        else:
            content = "Nobody got it right."

        answer_embed = discord.Embed(
            title=f"The words were:  `{'`, `'.join(ANAGRAMS_ALL[game.scrambled])}`!",
            colour=Colours.pink,
        )

        await ctx.send(content, embed=answer_embed)

        # Game is finished, let's remove it from the dict
        self.games.pop(ctx.channel.id)

    @commands.Cog.listener()
    async def on_message(self, message: discord.Message) -> None:
        """Check a message for an anagram attempt and pass to an ongoing game."""
        if message.author.bot or not message.guild:
            return

        game = self.games.get(message.channel.id)
        if not game:
            return

        await game.message_creation(message)


async def setup(bot: Bot) -> None:
    """Load the Anagram cog."""
    await bot.add_cog(Anagram(bot))