1
0
Fork 0
mirror of synced 2024-05-19 12:02:29 +12:00
Bonfire/cogs/games.py
2021-03-25 16:52:53 -08:00

94 lines
3.7 KiB
Python

from discord.ext import commands
import collections
import utils
class Games(commands.Cog):
def __init__(self):
self.running_games = collections.defaultdict(dict)
@commands.command(aliases=["word_chain", "しりとり", "シリトリ"])
@commands.max_concurrency(1, per=commands.BucketType.channel)
async def shiritori(self, ctx, *, word):
"""
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
The last player who entered a word cannot be the next person who enters a word
The kana ん cannot be used, as no word in Japanese starts with this
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]
letters = []
for reading in readings:
for char in reading:
if char.isalpha():
letters.append(char)
break
return letters
# 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"
)
# ん cannot be used
if any(char in last_letters for char in ("", "")):
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):
bot.add_cog(Games())