2016-08-15 11:26:10 +12:00
|
|
|
from discord.ext import commands
|
|
|
|
from discord.ext.commands.cooldowns import BucketType
|
|
|
|
|
|
|
|
from .utils import checks
|
|
|
|
|
2016-08-20 15:27:48 +12:00
|
|
|
import re
|
2016-09-01 14:01:43 +12:00
|
|
|
import random
|
|
|
|
|
|
|
|
phrases = ["Eat My Hat", "Par For the Course", "Raining Cats and Dogs", "Roll With the Punches",
|
|
|
|
"Curiosity Killed The Cat", "Man of Few Words", "Cry Over Spilt Milk", "Scot-free", "Rain on Your Parade",
|
|
|
|
"Go For Broke", "Shot In the Dark", "Mountain Out of a Molehill", "Jaws of Death", "A Dime a Dozen",
|
|
|
|
"Jig Is Up", "Elvis Has Left The Building", "Wake Up Call", "Jumping the Gun", "Up In Arms",
|
|
|
|
"Beating Around the Bush", "Flea Market", "Playing For Keeps", "Cut To The Chase", "Fight Fire With Fire",
|
|
|
|
"Keep Your Shirt On", "Poke Fun At", "Everything But The Kitchen Sink", "Jaws of Life",
|
|
|
|
"What Goes Up Must Come Down", "Give a Man a Fish", "Plot Thickens - The",
|
|
|
|
"Not the Sharpest Tool in the Shed", "Needle In a Haystack", "Right Off the Bat", "Throw In the Towel",
|
|
|
|
"Down To Earth", "Lickety Split", "I Smell a Rat", "Long In The Tooth",
|
|
|
|
"You Can't Teach an Old Dog New Tricks", "Back To the Drawing Board", "Down For The Count",
|
|
|
|
"On the Same Page", "Under Your Nose", "Cut The Mustard",
|
|
|
|
"If You Can't Stand the Heat, Get Out of the Kitchen", "Knock Your Socks Off", "Playing Possum",
|
|
|
|
"No-Brainer", "Money Doesn't Grow On Trees", "In a Pickle", "In the Red", "Fit as a Fiddle", "Hear, Hear",
|
|
|
|
"Hands Down", "Off One's Base", "Wild Goose Chase", "Keep Your Eyes Peeled", "A Piece of Cake",
|
|
|
|
"Foaming At The Mouth", "Go Out On a Limb", "Quick and Dirty", "Hit Below The Belt",
|
|
|
|
"Birds of a Feather Flock Together", "Wouldn't Harm a Fly", "Son of a Gun",
|
|
|
|
"Between a Rock and a Hard Place", "Down And Out", "Cup Of Joe", "Down To The Wire",
|
|
|
|
"Don't Look a Gift Horse In The Mouth", "Talk the Talk", "Close But No Cigar",
|
|
|
|
"Jack of All Trades Master of None", "High And Dry", "A Fool and His Money are Soon Parted",
|
|
|
|
"Every Cloud Has a Silver Lining", "Tough It Out", "Under the Weather", "Happy as a Clam",
|
|
|
|
"An Arm and a Leg", "Read 'Em and Weep", "Right Out of the Gate", "Know the Ropes",
|
|
|
|
"It's Not All It's Cracked Up To Be", "On the Ropes", "Burst Your Bubble", "Mouth-watering",
|
|
|
|
"Swinging For the Fences", "Fool's Gold", "On Cloud Nine", "Fish Out Of Water", "Ring Any Bells?",
|
|
|
|
"There's No I in Team", "Ride Him, Cowboy!", "Top Drawer", "No Ifs, Ands, or Buts",
|
|
|
|
"You Can't Judge a Book By Its Cover", "Don't Count Your Chickens Before They Hatch", "Cry Wolf",
|
|
|
|
"Beating a Dead Horse", "Goody Two-Shoes", "Heads Up", "Drawing a Blank", "Keep On Truckin'", "Tug of War",
|
|
|
|
"Short End of the Stick", "Hard Pill to Swallow", "Back to Square One", "Love Birds", "Dropping Like Flies",
|
|
|
|
"Break The Ice", "Knuckle Down", "Lovey Dovey", "Greased Lightning", "Let Her Rip", "All Greek To Me",
|
|
|
|
"Two Down, One to Go", "What Am I, Chopped Liver?", "It's Not Brain Surgery", "Like Father Like Son",
|
|
|
|
"Easy As Pie", "Elephant in the Room", "Quick On the Draw", "Barking Up The Wrong Tree",
|
|
|
|
"A Chip on Your Shoulder", "Put a Sock In It", "Quality Time", "Yada Yada", "Head Over Heels",
|
|
|
|
"My Cup of Tea", "Ugly Duckling", "Drive Me Nuts", "When the Rubber Hits the Road"]
|
2016-08-15 11:26:10 +12:00
|
|
|
|
2016-08-21 19:14:40 +12:00
|
|
|
|
2016-08-15 11:26:10 +12:00
|
|
|
class Game:
|
2016-09-01 14:01:43 +12:00
|
|
|
def __init__(self, word):
|
2016-08-15 11:26:10 +12:00
|
|
|
self.word = word
|
2016-08-16 15:30:52 +12:00
|
|
|
# This converts everything but spaces to a blank
|
2016-08-20 15:27:48 +12:00
|
|
|
self.blanks = "".join(letter if not re.search("[a-zA-Z0-9]", letter) else "_" for letter in word)
|
2016-08-15 12:00:01 +12:00
|
|
|
self.failed_letters = []
|
2016-08-15 11:26:10 +12:00
|
|
|
self.guessed_letters = []
|
|
|
|
self.fails = 0
|
2016-08-17 03:30:04 +12:00
|
|
|
|
2016-08-15 11:26:10 +12:00
|
|
|
def guess_letter(self, letter):
|
2016-08-16 15:30:52 +12:00
|
|
|
# No matter what, add this to guessed letters so we only have to do one check if a letter was already guessed
|
2016-08-15 12:00:01 +12:00
|
|
|
self.guessed_letters.append(letter)
|
2016-08-17 03:30:04 +12:00
|
|
|
if letter.lower() in self.word.lower():
|
2016-08-16 15:30:52 +12:00
|
|
|
# Replace every occurence of the guessed letter, with the correct letter
|
|
|
|
# Use the one in the word instead of letter, due to capitalization
|
2016-08-17 03:30:04 +12:00
|
|
|
self.blanks = "".join(
|
|
|
|
word_letter if letter.lower() == word_letter.lower() else self.blanks[i] for i, word_letter in
|
|
|
|
enumerate(self.word))
|
2016-08-15 11:26:10 +12:00
|
|
|
return True
|
|
|
|
else:
|
|
|
|
self.fails += 1
|
2016-08-15 12:00:01 +12:00
|
|
|
self.failed_letters.append(letter)
|
2016-08-15 11:26:10 +12:00
|
|
|
return False
|
2016-08-17 03:30:04 +12:00
|
|
|
|
2016-08-15 11:26:10 +12:00
|
|
|
def guess_word(self, word):
|
2016-08-15 11:33:42 +12:00
|
|
|
if word.lower() == self.word.lower():
|
2016-08-15 12:00:01 +12:00
|
|
|
self.blanks = self.word
|
2016-08-15 11:26:10 +12:00
|
|
|
return True
|
|
|
|
else:
|
|
|
|
self.fails += 1
|
|
|
|
return False
|
2016-08-17 03:30:04 +12:00
|
|
|
|
2016-08-15 11:26:10 +12:00
|
|
|
def win(self):
|
|
|
|
return self.word == self.blanks
|
2016-08-17 03:30:04 +12:00
|
|
|
|
2016-08-15 11:26:10 +12:00
|
|
|
def failed(self):
|
|
|
|
return self.fails == 7
|
2016-08-17 03:30:04 +12:00
|
|
|
|
2016-08-15 11:26:10 +12:00
|
|
|
def __str__(self):
|
2016-08-16 15:30:52 +12:00
|
|
|
# Here's our fancy formatting for the hangman picture
|
|
|
|
# Each position in the hangman picture is either a space, or part of the man, based on how many fails there are
|
2016-08-15 11:31:23 +12:00
|
|
|
man = " ——\n"
|
|
|
|
man += " | |\n"
|
|
|
|
man += " {} |\n".format("o" if self.fails > 0 else " ")
|
2016-08-17 03:30:04 +12:00
|
|
|
man += " {}{}{} |\n".format("/" if self.fails > 1 else " ", "|" if self.fails > 2 else " ",
|
|
|
|
"\\" if self.fails > 3 else " ")
|
2016-08-15 11:31:23 +12:00
|
|
|
man += " {} |\n".format("|" if self.fails > 4 else " ")
|
|
|
|
man += " {} {} |\n".format("/" if self.fails > 5 else " ", "\\" if self.fails > 6 else " ")
|
|
|
|
man += " |\n"
|
|
|
|
man += " ———————\n"
|
2016-08-15 11:26:10 +12:00
|
|
|
fmt = "```\n{}```".format(man)
|
2016-08-16 15:30:52 +12:00
|
|
|
# Then just add the guesses and the blanks to the string
|
2016-08-15 12:00:01 +12:00
|
|
|
fmt += "```\nGuesses: {}\nWord: {}```".format(", ".join(self.failed_letters), " ".join(self.blanks))
|
2016-08-15 11:26:10 +12:00
|
|
|
return fmt
|
2016-08-17 03:30:04 +12:00
|
|
|
|
|
|
|
|
2016-08-15 11:26:10 +12:00
|
|
|
class Hangman:
|
|
|
|
def __init__(self, bot):
|
|
|
|
self.bot = bot
|
|
|
|
self.games = {}
|
2016-08-17 03:30:04 +12:00
|
|
|
|
2016-08-15 11:26:10 +12:00
|
|
|
def create(self, word, ctx):
|
2016-08-16 15:30:52 +12:00
|
|
|
# Create a new game, then save it as the server's game
|
2016-09-01 14:01:43 +12:00
|
|
|
game = Game(word)
|
2016-08-15 11:26:10 +12:00
|
|
|
self.games[ctx.message.server.id] = game
|
|
|
|
return game
|
2016-08-17 03:30:04 +12:00
|
|
|
|
2016-08-15 11:26:10 +12:00
|
|
|
@commands.group(aliases=['hm'], pass_context=True, no_pm=True, invoke_without_command=True)
|
2016-11-11 17:49:16 +13:00
|
|
|
@commands.cooldown(1, 7, BucketType.user)
|
2016-08-15 14:10:12 +12:00
|
|
|
@checks.custom_perms(send_messages=True)
|
2016-08-15 11:26:10 +12:00
|
|
|
async def hangman(self, ctx, *, guess):
|
2016-11-29 17:55:55 +13:00
|
|
|
"""Makes a guess towards the server's currently running hangman game
|
|
|
|
|
|
|
|
EXAMPLE: !hangman e (or) !hangman The Phrase!
|
|
|
|
RESULT: Hopefully a win!"""
|
2016-08-15 11:26:10 +12:00
|
|
|
game = self.games.get(ctx.message.server.id)
|
|
|
|
if not game:
|
2016-09-11 20:32:36 +12:00
|
|
|
ctx.command.reset_cooldown(ctx)
|
2016-08-15 11:26:10 +12:00
|
|
|
await self.bot.say("There are currently no hangman games running!")
|
|
|
|
return
|
2016-08-17 03:30:04 +12:00
|
|
|
|
2016-08-16 15:30:52 +12:00
|
|
|
# Check if we are guessing a letter or a phrase. Only one letter can be guessed at a time
|
|
|
|
# So if anything more than one was provided, we're guessing at the phrase
|
|
|
|
# We're creating a fmt variable, so that we can add a message for if a guess was correct or not
|
|
|
|
# And also add a message for a loss/win
|
2016-08-15 11:26:10 +12:00
|
|
|
if len(guess) == 1:
|
2016-08-15 12:00:01 +12:00
|
|
|
if guess in game.guessed_letters:
|
2016-09-11 20:32:36 +12:00
|
|
|
ctx.command.reset_cooldown(ctx)
|
2016-08-15 12:00:01 +12:00
|
|
|
await self.bot.say("That letter has already been guessed!")
|
2016-08-16 15:30:52 +12:00
|
|
|
# Return here as we don't want to count this as a failure
|
2016-08-15 12:00:01 +12:00
|
|
|
return
|
2016-08-15 11:26:10 +12:00
|
|
|
if game.guess_letter(guess):
|
|
|
|
fmt = "That's correct!"
|
|
|
|
else:
|
|
|
|
fmt = "Sorry, that letter is not in the phrase..."
|
|
|
|
else:
|
|
|
|
if game.guess_word(guess):
|
|
|
|
fmt = "That's correct!"
|
|
|
|
else:
|
|
|
|
fmt = "Sorry that's not the correct phrase..."
|
2016-08-17 03:30:04 +12:00
|
|
|
|
2016-08-15 11:48:17 +12:00
|
|
|
if game.win():
|
2016-08-15 11:26:10 +12:00
|
|
|
fmt += " You guys got it! The word was `{}`".format(game.word)
|
2016-08-15 11:48:17 +12:00
|
|
|
del self.games[ctx.message.server.id]
|
2016-08-15 11:49:15 +12:00
|
|
|
elif game.failed():
|
2016-08-15 11:26:10 +12:00
|
|
|
fmt += " Sorry, you guys failed...the word was `{}`".format(game.word)
|
2016-08-15 11:48:17 +12:00
|
|
|
del self.games[ctx.message.server.id]
|
2016-08-15 11:26:10 +12:00
|
|
|
else:
|
|
|
|
fmt += str(game)
|
2016-08-17 03:30:04 +12:00
|
|
|
|
2016-08-15 11:26:10 +12:00
|
|
|
await self.bot.say(fmt)
|
2016-08-17 03:30:04 +12:00
|
|
|
|
2016-08-15 11:26:10 +12:00
|
|
|
@hangman.command(name='create', aliases=['start'], no_pm=True, pass_context=True)
|
2016-08-15 14:10:12 +12:00
|
|
|
@checks.custom_perms(send_messages=True)
|
2016-08-15 11:26:10 +12:00
|
|
|
async def create_hangman(self, ctx):
|
|
|
|
"""This is used to create a new hangman game
|
2017-01-06 07:13:22 +13:00
|
|
|
A predefined phrase will be randomly chosen as the phrase to use
|
2016-11-29 17:55:55 +13:00
|
|
|
|
|
|
|
EXAMPLE: !hangman start
|
|
|
|
RESULT: This is pretty obvious .-."""
|
2016-08-17 03:30:04 +12:00
|
|
|
|
2016-08-18 08:46:20 +12:00
|
|
|
# Only have one hangman game per server, since anyone
|
|
|
|
# In a server (except the creator) can guess towards the current game
|
|
|
|
if self.games.get(ctx.message.server.id) is not None:
|
2016-08-15 11:26:10 +12:00
|
|
|
await self.bot.say("Sorry but only one Hangman game can be running per server!")
|
|
|
|
return
|
2016-08-17 03:30:04 +12:00
|
|
|
|
2016-10-02 15:15:09 +13:00
|
|
|
game = self.create(random.SystemRandom().choice(phrases), ctx)
|
2016-08-16 15:30:52 +12:00
|
|
|
# Let them know the game has started, then print the current game so that the blanks are shown
|
2016-08-17 03:30:04 +12:00
|
|
|
await self.bot.say(
|
|
|
|
"Alright, a hangman game has just started, you can start guessing now!\n{}".format(str(game)))
|
2016-08-31 10:33:46 +12:00
|
|
|
|
2016-08-22 13:13:39 +12:00
|
|
|
@hangman.command(name='delete', aliases=['stop', 'remove', 'end'], pass_context=True, no_pm=True)
|
2016-08-22 08:23:47 +12:00
|
|
|
@checks.custom_perms(kick_members=True)
|
|
|
|
async def stop_game(self, ctx):
|
|
|
|
"""Force stops a game of hangman
|
|
|
|
This should realistically only be used in a situation like one player leaves
|
2016-11-29 17:55:55 +13:00
|
|
|
Hopefully a moderator will not abuse it, but there's not much we can do to avoid that
|
|
|
|
|
|
|
|
EXAMPLE: !hangman stop
|
|
|
|
RESULT: No more men being hung"""
|
2016-08-22 08:23:47 +12:00
|
|
|
if self.games.get(ctx.message.server.id) is None:
|
|
|
|
await self.bot.say("There are no Hangman games running on this server!")
|
|
|
|
return
|
2016-08-31 10:33:46 +12:00
|
|
|
|
2016-08-22 08:23:47 +12:00
|
|
|
del self.games[ctx.message.server.id]
|
|
|
|
await self.bot.say("I have just stopped the game of Hangman, a new should be able to be started now!")
|
2016-08-17 03:30:04 +12:00
|
|
|
|
2016-08-15 11:27:03 +12:00
|
|
|
|
|
|
|
def setup(bot):
|
|
|
|
bot.add_cog(Hangman(bot))
|