1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
import asyncio
import typing as t
import discord
from discord.ext.commands import Cog, Context
from bot.bot import SeasonalBot
from bot.constants import Emojis
CONFIRMATION_MESSAGE = (
"{opponent}, {requester} want to play Tic-Tac-Toe against you. React to this message with "
f"{Emojis.confirmation} to accept or with {Emojis.decline} to decline."
)
class Player:
"""Class that contains information about player and functions that interact with player."""
def __init__(self, user: discord.User, ctx: Context):
self.user = user
self.ctx = ctx
class Game:
"""Class that contains information and functions about Tic Tac Toe game."""
def __init__(self, channel: discord.TextChannel, players: t.List[Player], ctx: Context):
self.channel = channel
self.players = players
self.ctx = ctx
self.current = self.players[0]
self.next = self.players[1]
self.winner: t.Optional[Player] = None
self.loser: t.Optional[Player] = None
async def get_confirmation(self) -> t.Tuple[bool, t.Optional[str]]:
"""Ask does user want to play TicTacToe against requester. First player is always requester."""
confirm_message = await self.ctx.send(
CONFIRMATION_MESSAGE.format(
opponent=self.players[1].user.mention,
requester=self.players[0].user.mention
)
)
await confirm_message.add_reaction(Emojis.confirmation)
await confirm_message.add_reaction(Emojis.decline)
def confirm_check(reaction: discord.Reaction, user: discord.User) -> bool:
return (
reaction.emoji in (Emojis.confirmation, Emojis.decline)
and reaction.message.id == confirm_message.id
and user == self.players[1].user
)
try:
reaction, user = await self.ctx.bot.wait_for(
"reaction_add",
timeout=60.0,
check=confirm_check
)
except asyncio.TimeoutError:
await confirm_message.delete()
return False, "Running out of time... Cancelled game."
await confirm_message.delete()
if reaction.emoji == Emojis.confirmation:
return True, None
else:
return False, "User declined"
async def add_reactions(self, msg: discord.Message) -> None:
"""Add number emojis to message."""
for nr in Emojis.number_emojis:
await msg.add_reaction(nr)
class TicTacToe(Cog):
"""TicTacToe cog contains tic-tac-toe game commands."""
def __init__(self, bot: SeasonalBot):
self.bot = bot
self.games: t.List[Game] = []
def setup(bot: SeasonalBot) -> None:
"""Load TicTacToe Cog."""
bot.add_cog(TicTacToe(bot))
|