From c03e2280631f296a93cbc4bab0c634210ea0eeac Mon Sep 17 00:00:00 2001 From: Dan Hess Date: Thu, 25 Mar 2021 16:52:53 -0800 Subject: [PATCH] Fix up shiritori --- cogs/games.py | 132 +++++++++++++++++++++----------------------------- 1 file changed, 54 insertions(+), 78 deletions(-) diff --git a/cogs/games.py b/cogs/games.py index 118fff7..143d4ff 100644 --- a/cogs/games.py +++ b/cogs/games.py @@ -8,13 +8,11 @@ class Games(commands.Cog): def __init__(self): self.running_games = collections.defaultdict(dict) - @commands.guild_only() - @commands.is_owner() @commands.command(aliases=["word_chain", "しりとり", "シリトリ"]) @commands.max_concurrency(1, per=commands.BucketType.channel) - async def shiritori(self, ctx, *, start_word): + async def shiritori(self, ctx, *, word): """ - Starts a game of Shiritori, in which the last letter of the last word given + Starts or play on a game of Shiritori, in which the last letter of the last word given has to be the first letter of the next word given. For example, if the word given is apple, then the next word can be elephant because apple ends in e and elephant begins in e @@ -23,6 +21,18 @@ class Games(commands.Cog): The word used cannot be a previously given word """ game = self.running_games["shiritori"].get(ctx.channel.id) + # Ensure only one game is happening at once + if game is not None: + if ctx.author not in game["players"]: + game["players"].append(ctx.author) + else: + self.running_games["shiritori"][ctx.channel.id] = { + "players": [ctx.author], + "words_used": [], + "last_letters": [], + "last_author": ctx.author, + } + game = self.running_games["shiritori"].get(ctx.channel.id) def grab_letter(readings, last=True): readings = [reversed(word) if last else iter(word) for word in readings] @@ -33,84 +43,50 @@ class Games(commands.Cog): for char in reading: if char.isalpha(): letters.append(char) + break - def check(message): - # Ensure it's in the same channel - if message.channel != ctx.channel: - return False - # Ensure we aren't listening to a bot (like ourselves for example) - elif message.author.bot: - return False - # The last person who gave a message cannot be the next one as well - elif last_author is not None and message.author == last_author: - return False - # If no game is running then how did this even happen!? - elif game is None: - return False - # If the author is not a player - elif message.author not in game["players"]: - return False - # Otherwise we good - else: - return True + return letters - # Setup the info needed for the game - message = ctx.message - message.content = start_word - last_letters = None - words_used = [] + # Don't allow last author to guess again + if game["words_used"] and ctx.author == game["last_author"]: + return await ctx.send("You guessed last, someone else's turn") + is_noun, readings = await utils.readings_for_word(word) + # Only nouns can be used + if not is_noun: + self.running_games["shiritori"][ctx.channel.id] = None + return await ctx.send( + f"Game over! {ctx.author} loses, only nouns can be used" + ) + # Grab the first letter of this new word and check it + first_letters = grab_letter(readings, last=False) + last_letters = grab_letter(readings, last=False) + # Include extra check for if this is the first word + if game["words_used"]: + # Check if there's a match between first and last letters + if not any(char in first_letters for char in game["last_letters"]): + self.running_games["shiritori"][ctx.channel.id] = None + return await ctx.send( + f"Game over! {ctx.author} loses, first letter of {word} did not match last letter used" + ) - # Ensure only one game is happening at once - if game is not None: - if ctx.author not in game["players"]: - game["players"].append(ctx.author) - await ctx.message.add_reaction("✅") - else: - await ctx.message.add_reaction("✅") - else: - self.running_games["shiritori"][ctx.channel.id] = {"players": []} - - await ctx.send( - f"Shiritori game started! First word is `{start_word}`, any responses after this" - "count towards the game" - ) - - while True: - is_noun, readings = await utils.readings_for_word(message.content) - # Only nouns can be used - if not is_noun: - break - # Grab the first letter of this new word and check it - first_letters = grab_letter(readings, last=False) - # Include extra check for if this is the first word - if words_used: - # Check if there's a match between first and last letters - if not any(char in first_letters for char in last_letters): - break - # Now set the "last" information, to start checking if it's correct - last_words = readings - last_letters = grab_letter(last_words) - last_author = message.author - - # Extra check for the japanese version, ん cannot be used - if any(char in last_letters for char in ("ん", "ン")): - break - # Cannot reuuse words; though make sure this doesn't get caught on the very first usage - if any(word in words_used for word in last_words) and len(words_used) >= 1: - break - - # If we're here, then the last letter used was valid - words_used.extend(last_words) - await message.add_reaction("✅") - message = await ctx.bot.wait_for("message", check=check) - - # If we're here, game over, someone messed up - self.running_games["shiritori"][ctx.channel.id] = False - await message.add_reaction("❌") + # ん cannot be used if any(char in last_letters for char in ("ん", "ン")): - await ctx.send("Wrong! ん cannot be used as the last kana!") - else: - await ctx.send(f"Wrong! {message.author.mention} is a loser!") + self.running_games["shiritori"][ctx.channel.id] = None + return await ctx.send( + f"Game over! {ctx.author} loses, last letter cannot be ん" + ) + # Cannot reuuse words + if word in game["words_used"]: + self.running_games["shiritori"][ctx.channel.id] = None + return await ctx.send( + f"Game over! {ctx.author} loses, {word} has already been used" + ) + + # If we're here, then the last letter used was valid, save stuff + game["words_used"].append(word) + game["last_letters"] = last_letters + game["last_author"] = ctx.author + await ctx.message.add_reaction("✅") def setup(bot):