You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Fox-V3/hangman/hangman.py

349 lines
13 KiB

from collections import defaultdict
7 years ago
from random import randint
7 years ago
import discord
from redbot.core import Config, checks, commands
from redbot.core.data_manager import cog_data_path
7 years ago
class Hangman:
"""Lets anyone play a game of hangman with custom phrases"""
7 years ago
navigate = "🔼🔽"
letters = "🇦🇧🇨🇩🇪🇫🇬🇭🇮🇯🇰🇱🇲🇳🇴🇵🇶🇷🇸🇹🇺🇻🇼🇽🇾🇿"
7 years ago
def __init__(self, bot):
self.bot = bot
self.config = Config.get_conf(self, identifier=1049711010310997110)
default_guild = {
"theface": ':thinking:',
"emojis": True,
}
self.config.register_guild(**default_guild)
7 years ago
self.the_data = defaultdict(
lambda: {"running": False, "hangman": 0, "guesses": [], "trackmessage": False, "answer": ''})
7 years ago
self.path = str(cog_data_path(self)).replace('\\', '/')
self.answer_path = self.path + "/bundled_data/hanganswers.txt"
7 years ago
self.winbool = defaultdict(lambda: False)
self.hanglist = {}
async def _update_hanglist(self):
for guild in self.bot.guilds:
theface = await self.config.guild(guild).theface()
self.hanglist[guild] = (
""">
\_________
|/
|
|
|
|
|
|\___
""",
""">
\_________
|/ |
|
|
|
|
|
|\___
H""",
""">
\_________
|/ |
7 years ago
| """ + theface + """
|
|
|
|
|\___
HA""",
""">
\________
|/ |
7 years ago
| """ + theface + """
| |
| |
|
|
|\___
HAN""",
""">
\_________
|/ |
7 years ago
| """ + theface + """
| /|
| |
|
|
|\___
HANG""",
""">
\_________
|/ |
7 years ago
| """ + theface + """
| /|\
| |
|
|
|\___
HANGM""",
""">
\________
|/ |
7 years ago
| """ + theface + """
| /|\
| |
| /
|
|\___
HANGMA""",
""">
\________
|/ |
7 years ago
| """ + theface + """
| /|\
| |
| / \
|
|\___
HANGMAN""")
7 years ago
@commands.group(aliases=['sethang'], pass_context=True)
@checks.mod_or_permissions(administrator=True)
async def hangset(self, ctx):
"""Adjust hangman settings"""
if not ctx.invoked_subcommand:
pass
7 years ago
@hangset.command(pass_context=True)
async def face(self, ctx: commands.Context, theface):
7 years ago
message = ctx.message
7 years ago
# Borrowing FlapJack's emoji validation
# (https://github.com/flapjax/FlapJack-Cogs/blob/master/smartreact/smartreact.py)
7 years ago
if theface[:2] == "<:":
theface = [r for r in self.bot.emojis if r.id == theface.split(':')[2][:-1]][0]
7 years ago
try:
# Use the face as reaction to see if it's valid (THANKS FLAPJACK <3)
await message.add_reaction(theface)
7 years ago
except discord.errors.HTTPException:
await ctx.send("That's not an emoji I recognize.")
return
await self.config.guild(ctx.guild).theface.set(theface)
await self._update_hanglist()
await ctx.send("Face has been updated!")
7 years ago
@hangset.command(pass_context=True)
async def toggleemoji(self, ctx: commands.Context):
"""Toggles whether to automatically react with the alphabet"""
current = await self.config.guild(ctx.guild).emojis()
await self.config.guild(ctx.guild).emojis.set(not current)
await ctx.send("Emoji Letter reactions have been set to {}".format(not current))
7 years ago
@commands.command(aliases=['hang'], pass_context=True)
7 years ago
async def hangman(self, ctx, guess: str = None):
7 years ago
"""Play a game of hangman against the bot!"""
if guess is None:
if self.the_data[ctx.guild]["running"]:
await ctx.send("Game of hangman is already running!\nEnter your guess!")
7 years ago
await self._printgame(ctx.channel)
7 years ago
"""await self.bot.send_cmd_help(ctx)"""
else:
await ctx.send("Starting a game of hangman!")
self._startgame(ctx.guild)
await self._printgame(ctx.channel)
elif not self.the_data[ctx.guild]["running"]:
await ctx.send("Game of hangman is not yet running!\nStarting a game of hangman!")
self._startgame(ctx.guild)
await self._printgame(ctx.channel)
7 years ago
else:
7 years ago
await ctx.send("Guess by reacting to the message")
# await self._guessletter(guess, ctx.channel)
7 years ago
def _startgame(self, guild):
7 years ago
"""Starts a new game of hangman"""
self.the_data[guild]["answer"] = self._getphrase().upper()
self.the_data[guild]["hangman"] = 0
self.the_data[guild]["guesses"] = []
self.winbool[guild] = False
self.the_data[guild]["running"] = True
self.the_data[guild]["trackmessage"] = False
7 years ago
def _stopgame(self, guild):
7 years ago
"""Stops the game in current state"""
self.the_data[guild]["running"] = False
7 years ago
self.the_data[guild]["trackmessage"] = False
async def _checkdone(self, channel):
if self.winbool[channel.guild]:
await channel.send("You Win!")
self._stopgame(channel.guild)
7 years ago
elif self.the_data[channel.guild]["hangman"] >= 7:
7 years ago
await channel.send("You Lose!\nThe Answer was: **" + self.the_data[channel.guild]["answer"] + "**")
self._stopgame(channel.guild)
7 years ago
7 years ago
def _getphrase(self):
"""Get a new phrase for the game and returns it"""
7 years ago
7 years ago
with open(self.answer_path, 'r') as phrasefile:
7 years ago
phrases = phrasefile.readlines()
7 years ago
7 years ago
outphrase = ""
while outphrase == "":
7 years ago
outphrase = phrases[randint(0, len(phrases) - 1)].partition(" (")[0]
7 years ago
return outphrase
7 years ago
def _hideanswer(self, guild):
7 years ago
"""Returns the obscured answer"""
out_str = ""
7 years ago
7 years ago
self.winbool[guild] = True
for i in self.the_data[guild]["answer"]:
7 years ago
if i == " " or i == "-":
7 years ago
out_str += i * 2
elif i in self.the_data[guild]["guesses"] or i not in "ABCDEFGHIJKLMNOPQRSTUVWXYZ":
7 years ago
out_str += "__" + i + "__ "
7 years ago
else:
out_str += "**\_** "
self.winbool[guild] = False
7 years ago
7 years ago
return out_str
7 years ago
def _guesslist(self, guild):
7 years ago
"""Returns the current letter list"""
out_str = ""
for i in self.the_data[guild]["guesses"]:
7 years ago
out_str += str(i) + ","
out_str = out_str[:-1]
7 years ago
7 years ago
return out_str
7 years ago
async def _guessletter(self, guess, message):
7 years ago
"""Checks the guess on a letter and prints game if acceptable guess"""
channel = message.channel
if guess.upper() not in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" or len(guess) != 1:
await channel.send("Invalid guess. Only A-Z is accepted")
7 years ago
return
if guess.upper() in self.the_data[channel.guild]["guesses"]:
await channel.send("Already guessed that! Try again")
7 years ago
return
if guess.upper() not in self.the_data[channel.guild]["answer"]:
self.the_data[channel.guild]["hangman"] += 1
7 years ago
self.the_data[channel.guild]["guesses"].append(guess.upper())
7 years ago
await self._reprintgame(message)
7 years ago
async def on_react(self, reaction, user):
7 years ago
""" Thanks to flapjack reactpoll for guidelines
https://github.com/flapjax/FlapJack-Cogs/blob/master/reactpoll/reactpoll.py"""
7 years ago
if reaction.message.id != self.the_data[user.guild]["trackmessage"]:
7 years ago
return
7 years ago
7 years ago
if user == self.bot.user:
return # Don't react to bot's own reactions
7 years ago
message = reaction.message
emoji = reaction.emoji
7 years ago
7 years ago
if str(emoji) in self.letters:
letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[self.letters.index(str(emoji))]
7 years ago
await self._guessletter(letter, message)
await message.remove_reaction(emoji, user)
await message.remove_reaction(emoji, self.bot.user)
7 years ago
7 years ago
if str(emoji) in self.navigate:
if str(emoji) == self.navigate[0]:
await self._reactmessage_am(message)
7 years ago
7 years ago
if str(emoji) == self.navigate[-1]:
await self._reactmessage_nz(message)
7 years ago
7 years ago
async def _reactmessage_menu(self, message):
"""React with menu options"""
if not await self.config.guild(message.guild).emojis():
return
await message.clear_reactions()
7 years ago
await message.add_reaction(self.navigate[0])
await message.add_reaction(self.navigate[-1])
7 years ago
7 years ago
async def _reactmessage_am(self, message):
if not await self.config.guild(message.guild).emojis():
return
await message.clear_reactions()
7 years ago
for x in range(len(self.letters)):
7 years ago
if x in [i for i, b in enumerate("ABCDEFGHIJKLM") if b not in self._guesslist(message.guild)]:
await message.add_reaction(self.letters[x])
7 years ago
await message.add_reaction(self.navigate[-1])
7 years ago
async def _reactmessage_nz(self, message):
if not await self.config.guild(message.guild).emojis():
return
7 years ago
await message.clear_reactions()
7 years ago
for x in range(len(self.letters)):
7 years ago
if x in [i for i, b in enumerate("NOPQRSTUVWXYZ") if b not in self._guesslist(message.guild)]:
7 years ago
await message.add_reaction(self.letters[x + 13])
7 years ago
7 years ago
await message.add_reaction(self.navigate[0])
7 years ago
def _make_say(self, guild):
c_say = "Guess this: " + str(self._hideanswer(guild)) + "\n"
c_say += "Used Letters: " + str(self._guesslist(guild)) + "\n"
c_say += self.hanglist[guild][self.the_data[guild]["hangman"]] + "\n"
c_say += self.navigate[0] + " for A-M, " + self.navigate[-1] + " for N-Z"
return c_say
async def _reprintgame(self, message):
if message.guild not in self.hanglist:
7 years ago
await self._update_hanglist()
c_say = self._make_say(message.guild)
7 years ago
7 years ago
await message.edit(content=c_say)
self.the_data[message.guild]["trackmessage"] = message.id
7 years ago
await self._checkdone(message.channel)
7 years ago
async def _printgame(self, channel):
"""Print the current state of game"""
if channel.guild not in self.hanglist:
await self._update_hanglist()
c_say = self._make_say(channel.guild)
7 years ago
message = await channel.send(c_say)
self.the_data[channel.guild]["trackmessage"] = message.id
7 years ago
await self._reactmessage_menu(message)
await self._checkdone(channel)