95 lines
2.9 KiB
Python
95 lines
2.9 KiB
Python
from __future__ import annotations
|
|
|
|
import asyncio
|
|
import random
|
|
from typing import ClassVar, Optional
|
|
|
|
import discord
|
|
from discord.ext import commands
|
|
|
|
from .utils import DiscordColor, DEFAULT_COLOR
|
|
|
|
|
|
class RockPaperScissors:
|
|
message: discord.Message
|
|
|
|
OPTIONS: ClassVar[tuple[str, str, str]] = ("\U0001faa8", "\U00002702", "\U0001f4f0")
|
|
BEATS: ClassVar[dict[str, str]] = {
|
|
OPTIONS[0]: OPTIONS[1],
|
|
OPTIONS[1]: OPTIONS[2],
|
|
OPTIONS[2]: OPTIONS[0],
|
|
}
|
|
|
|
def check_win(self, bot_choice: str, user_choice: str) -> bool:
|
|
return self.BEATS[user_choice] == bot_choice
|
|
|
|
async def wait_for_choice(
|
|
self, ctx: commands.Context[commands.Bot], *, timeout: float
|
|
) -> str:
|
|
def check(reaction: discord.Reaction, user: discord.User) -> bool:
|
|
return (
|
|
str(reaction.emoji) in self.OPTIONS
|
|
and user == ctx.author
|
|
and reaction.message == self.message
|
|
)
|
|
|
|
reaction, _ = await ctx.bot.wait_for(
|
|
"reaction_add", timeout=timeout, check=check
|
|
)
|
|
return str(reaction.emoji)
|
|
|
|
async def start(
|
|
self,
|
|
ctx: commands.Context[commands.Bot],
|
|
*,
|
|
timeout: Optional[float] = None,
|
|
embed_color: DiscordColor = DEFAULT_COLOR,
|
|
) -> discord.Message:
|
|
"""
|
|
Starts the Rock Paper Scissors game.
|
|
|
|
Parameters
|
|
----------
|
|
ctx : commands.Context
|
|
The context of the invoking command.
|
|
timeout : Optional[float], optional
|
|
The timeout for waiting, by default None.
|
|
embed_color : DiscordColor, optional
|
|
The color of the game embed, by default DEFAULT_COLOR.
|
|
|
|
Returns
|
|
-------
|
|
discord.Message
|
|
Returns the game message.
|
|
"""
|
|
embed = discord.Embed(
|
|
title="Rock Paper Scissors",
|
|
description="React to play!",
|
|
color=discord.Color.random(),
|
|
)
|
|
self.message = await ctx.send(embed=embed)
|
|
|
|
for option in self.OPTIONS:
|
|
await self.message.add_reaction(option)
|
|
|
|
bot_choice = random.choice(self.OPTIONS)
|
|
|
|
try:
|
|
user_choice = await self.wait_for_choice(ctx, timeout=timeout)
|
|
except asyncio.TimeoutError:
|
|
embed.description = "You took too long to respond!"
|
|
await self.message.edit(embed=embed)
|
|
return self.message
|
|
|
|
if user_choice == bot_choice:
|
|
embed.description = f"**Tie!**\nWe both picked {user_choice}"
|
|
elif self.check_win(bot_choice, user_choice):
|
|
embed.description = (
|
|
f"**You Won!**\nYou picked {user_choice} and I picked {bot_choice}."
|
|
)
|
|
else:
|
|
embed.description = f"**You Lost!**\nI picked {bot_choice} and you picked {user_choice}."
|
|
|
|
await self.message.edit(embed=embed)
|
|
return self.message
|