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

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