Merge branch 'hangman-develop'

pull/5/head
Bobloy 7 years ago
commit 7b0b6b9a16

@ -0,0 +1,9 @@
from .hangman import Hangman
from redbot.core import data_manager
def setup(bot):
n = Hangman(bot)
data_manager.load_bundled_data(n, __file__)
bot.add_cog(n)
bot.add_listener(n._on_react, "on_reaction_add")

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

@ -1,14 +1,20 @@
{ {
"AUTHOR": "Bobloy", "author": [
"DESCRIPTION": "Hangman Cog for Red Discord bot. Play a game of Hangman with your friends!", "Bobloy"
"INSTALL_MSG": "Thank you for installing Hangman! Play with [p]hangman, edit with [p]hangset", ],
"NAME": "Hangman", "bot_version": [
"SHORT": "Play a game of Hangman with your friends!", 3,
"TAGS": [ 0,
"fox", 0
"bobloy", ],
"fun", "description": "Play Hangman with your friends",
"game" "hidden": false,
], "install_msg": "Thank you for installing Hangman!",
"HIDDEN": false "requirements": [],
"short": "Play Hangman",
"tags": [
"game",
"fun",
"bobloy"
]
} }
Loading…
Cancel
Save