Files
Mace-AIO-Discord-Bot---With…/bot/games/button_games/tictactoe_buttons.py

143 lines
5.3 KiB
Python

# ╔══════════════════════════════════════════════════════════════════╗
# ║ ║
# ║ ░█▀▀░█▀█░█▀▄░█▀▀░█░█ ░█▀▄░█▀▀░█░█░█▀▀ ║
# ║ ░█░░░█░█░█░█░█▀▀░▄▀▄ ░█░█░█▀▀░▀▄▀░▀▀█ ║
# ║ ░▀▀▀░▀▀▀░▀▀░░▀▀▀░▀░▀ ░▀▀░░▀▀▀░░▀░░▀▀▀ ║
# ║ ║
# ║ © 2026 CodeX Devs — All Rights Reserved ║
# ║ ║
# ║ discord ── https://discord.gg/codexdev ║
# ║ youtube ── https://youtube.com/@CodeXDevs ║
# ║ github ── https://github.com/RayExo ║
# ║ ║
# ╚══════════════════════════════════════════════════════════════════╝
from __future__ import annotations
from typing import ClassVar, Optional
import discord
from discord.ext import commands
from ..tictactoe import Tictactoe
from ..utils import *
class TTTButton(discord.ui.Button["TTTView"]):
def __init__(self, label: str, style: discord.ButtonStyle, *, row: int, col: int):
super().__init__(
label=label,
style=style,
row=row,
)
self.col = col
async def callback(self, interaction: discord.Interaction) -> None:
user = interaction.user
game = self.view.game
if user not in (game.cross, game.circle):
return await interaction.response.send_message(
"You are not part of this game!", ephemeral=True
)
if user != game.turn:
return await interaction.response.send_message(
"it is not your turn!", ephemeral=True
)
self.label = game.player_to_emoji[user]
self.disabled = True
game.board[self.row][self.col] = self.label
game.turn = game.circle if user == game.cross else game.cross
tie = all(button.disabled for button in self.view.children)
if game_over := game.is_game_over(tie=tie):
if game.winning_indexes:
self.view.disable_all()
game.create_streak()
self.view.stop()
embed = game.make_embed(game_over=game_over or tie)
await interaction.response.edit_message(embed=embed, view=self.view)
class TTTView(BaseView):
def __init__(self, game: BetaTictactoe, *, timeout: float) -> None:
super().__init__(timeout=timeout)
self.game = game
for x, row in enumerate(game.board):
for y, square in enumerate(row):
button = TTTButton(
label=square,
style=self.game.button_style,
row=x,
col=y,
)
self.add_item(button)
class BetaTictactoe(Tictactoe):
"""
Tictactoe(buttons) game
"""
BLANK: ClassVar[str] = "\u200b"
CIRCLE: ClassVar[str] = "O"
CROSS: ClassVar[str] = "X"
def create_streak(self) -> None:
chunked = chunk(self.view.children, count=3)
for row, col in self.winning_indexes:
button: TTTButton = chunked[row][col]
button.style = self.win_button_style
async def start(
self,
ctx: commands.Context[commands.Bot],
button_style: discord.ButtonStyle = discord.ButtonStyle.green,
*,
embed_color: DiscordColor = DEFAULT_COLOR,
win_button_style: discord.ButtonStyle = discord.ButtonStyle.red,
timeout: Optional[float] = None,
) -> discord.Message:
"""
starts the tictactoe(buttons) game
Parameters
----------
ctx : commands.Context
the context of the invokation command
button_style : discord.ButtonStyle, optional
the primary button style to use, by default discord.ButtonStyle.green
embed_color : DiscordColor, optional
the color of the game embed, by default DEFAULT_COLOR
win_button_style : discord.ButtonStyle, optional
the button style to use to show the winning line, by default discord.ButtonStyle.red
timeout : Optional[float], optional
the timeout for the view, by default None
Returns
-------
discord.Message
returns the game message
"""
self.embed_color = discord.Color.random()
self.button_style = button_style
self.win_button_style = win_button_style
self.view = TTTView(self, timeout=timeout)
self.message = await ctx.send(embed=self.make_embed(), view=self.view)
await double_wait(
wait_for_delete(ctx, self.message, user=(self.cross, self.circle)),
self.view.wait(),
)
return self.message