✨ game stuff
This commit is contained in:
@ -22,12 +22,46 @@ create_actionrow)
|
||||
from discord_slash.model import ButtonStyle
|
||||
|
||||
from gwendolyn.utils import encode_id
|
||||
from .game_base import BoardGame
|
||||
|
||||
ROWCOUNT = 6
|
||||
COLUMNCOUNT = 7
|
||||
|
||||
def _encode_board_string(board: list):
|
||||
string = [str(i) for row in board for i in row]
|
||||
|
||||
class ConnectFour():
|
||||
while len(string) > 0 and string[0] == "0":
|
||||
string = string[1:]
|
||||
|
||||
if string == "":
|
||||
string = "0"
|
||||
|
||||
dec = 0
|
||||
for i, digit in enumerate(string[::-1]):
|
||||
dec += (3**i)*int(digit)
|
||||
|
||||
return str(dec)
|
||||
|
||||
def _decode_board_string(board_string: str):
|
||||
dec = int(board_string)
|
||||
string = []
|
||||
while dec:
|
||||
string.append(str(dec % 3))
|
||||
dec = dec // 3
|
||||
|
||||
while len(string) < ROWCOUNT * COLUMNCOUNT:
|
||||
string.append("0")
|
||||
|
||||
string = string[::-1]
|
||||
|
||||
board = [
|
||||
[int(x) for x in string[i*COLUMNCOUNT:i*COLUMNCOUNT+COLUMNCOUNT]]
|
||||
for i in range(ROWCOUNT)]
|
||||
|
||||
return board
|
||||
|
||||
|
||||
class ConnectFour(BoardGame):
|
||||
"""
|
||||
Deals with connect four commands and logic.
|
||||
|
||||
@ -41,8 +75,7 @@ class ConnectFour():
|
||||
|
||||
def __init__(self, bot):
|
||||
"""Initialize the class."""
|
||||
self.bot = bot
|
||||
self.draw = DrawConnectFour(bot)
|
||||
super().__init__(bot, "connectfour", DrawConnectFour(bot))
|
||||
self.get_name = self.bot.database_funcs.get_name
|
||||
# pylint: disable=invalid-name
|
||||
self.AISCORES = {
|
||||
@ -57,39 +90,6 @@ class ConnectFour():
|
||||
}
|
||||
# pylint: enable=invalid-name
|
||||
|
||||
def _encode_board_string(self, board: list):
|
||||
string = [str(i) for row in board for i in row]
|
||||
|
||||
while len(string) > 0 and string[0] == "0":
|
||||
string = string[1:]
|
||||
|
||||
if string == "":
|
||||
string = "0"
|
||||
|
||||
dec = 0
|
||||
for i, digit in enumerate(string[::-1]):
|
||||
dec += (3**i)*int(digit)
|
||||
|
||||
return str(dec)
|
||||
|
||||
def _decode_board_string(self, board_string: str):
|
||||
dec = int(board_string)
|
||||
string = []
|
||||
while dec:
|
||||
string.append(str(dec % 3))
|
||||
dec = dec // 3
|
||||
|
||||
while len(string) < ROWCOUNT * COLUMNCOUNT:
|
||||
string.append("0")
|
||||
|
||||
string = string[::-1]
|
||||
|
||||
board = [
|
||||
[int(x) for x in string[i*COLUMNCOUNT:i*COLUMNCOUNT+COLUMNCOUNT]]
|
||||
for i in range(ROWCOUNT)]
|
||||
|
||||
return board
|
||||
|
||||
async def start(self, ctx: SlashContext,
|
||||
opponent: Union[int, discord.User]):
|
||||
"""
|
||||
@ -106,128 +106,90 @@ class ConnectFour():
|
||||
searches when minimaxing.
|
||||
"""
|
||||
await self.bot.defer(ctx)
|
||||
user = ctx.author.id
|
||||
channel = str(ctx.channel_id)
|
||||
|
||||
started_game = False
|
||||
can_start = True
|
||||
opponent_info = self._test_opponent(ctx, opponent)
|
||||
if not opponent_info:
|
||||
return
|
||||
|
||||
if isinstance(opponent, int):
|
||||
# Opponent is Gwendolyn
|
||||
if opponent in range(1, 6):
|
||||
difficulty = int(opponent)
|
||||
difficulty_text = f" with difficulty {difficulty}"
|
||||
opponent = self.bot.user.id
|
||||
else:
|
||||
send_message = "Difficulty doesn't exist"
|
||||
log_message = "They challenged a difficulty that doesn't exist"
|
||||
can_start = False
|
||||
elif isinstance(opponent, discord.User):
|
||||
if opponent.bot:
|
||||
# User has challenged a bot
|
||||
if opponent == self.bot.user:
|
||||
# It was Gwendolyn
|
||||
difficulty = 3
|
||||
difficulty_text = f" with difficulty {difficulty}"
|
||||
opponent = self.bot.user.id
|
||||
else:
|
||||
send_message = "You can't challenge a bot!"
|
||||
log_message = "They tried to challenge a bot"
|
||||
can_start = False
|
||||
else:
|
||||
# Opponent is another player
|
||||
if ctx.author != opponent:
|
||||
opponent = opponent.id
|
||||
difficulty = 5
|
||||
difficulty_text = ""
|
||||
else:
|
||||
send_message = "You can't play against yourself"
|
||||
log_message = "They tried to play against themself"
|
||||
can_start = False
|
||||
difficulty = opponent_info[0]
|
||||
difficulty_text = opponent_info[1]
|
||||
|
||||
if can_start:
|
||||
board = [[0 for _ in range(COLUMNCOUNT)] for _ in range(ROWCOUNT)]
|
||||
players = [user, opponent]
|
||||
random.shuffle(players)
|
||||
board = [[0 for _ in range(COLUMNCOUNT)] for _ in range(ROWCOUNT)]
|
||||
players = [ctx.author.id, opponent]
|
||||
random.shuffle(players)
|
||||
|
||||
self.draw.draw_image(channel, board, 0, [0,0], "", players)
|
||||
self.draw.draw_image(channel, board, players, [0, [0,0], ""], players)
|
||||
|
||||
gwendolyn_turn = (players[0] == self.bot.user.id)
|
||||
started_game = True
|
||||
opponent_name = self.get_name(f"#{opponent}")
|
||||
turn_name = self.get_name(f"#{players[0]}")
|
||||
|
||||
opponent_name = self.get_name(f"#{opponent}")
|
||||
turn_name = self.get_name(f"#{players[0]}")
|
||||
|
||||
started_text = "Started game against {}{}.".format(
|
||||
opponent_name,
|
||||
difficulty_text
|
||||
)
|
||||
turn_text = f"It's {turn_name}'s turn"
|
||||
send_message = f"{started_text} {turn_text}"
|
||||
log_message = "They started a game"
|
||||
|
||||
self.bot.log(log_message)
|
||||
await ctx.send(send_message)
|
||||
started_text = "Started game against {}{}.".format(
|
||||
opponent_name,
|
||||
difficulty_text
|
||||
)
|
||||
turn_text = f"It's {turn_name}'s turn"
|
||||
await ctx.send(f"{started_text} {turn_text}")
|
||||
self.bot.log("They started a game")
|
||||
|
||||
# Sets the whole game in motion
|
||||
if started_game:
|
||||
boards_path = "gwendolyn/resources/games/connect_four_boards/"
|
||||
file_path = f"{boards_path}board{ctx.channel_id}.png"
|
||||
image_message = await ctx.send(file=discord.File(file_path))
|
||||
|
||||
board_string = self._encode_board_string(board)
|
||||
if gwendolyn_turn:
|
||||
await self._connect_four_ai(
|
||||
ctx, board_string, players, difficulty, image_message.id
|
||||
)
|
||||
else:
|
||||
buttons = []
|
||||
for i in range(7):
|
||||
custom_id = encode_id(
|
||||
[
|
||||
"connectfour",
|
||||
"place",
|
||||
str(players[0]),
|
||||
board_string,
|
||||
str(i),
|
||||
str(players[0]),
|
||||
str(players[1]),
|
||||
str(difficulty),
|
||||
str(image_message.id)
|
||||
]
|
||||
)
|
||||
buttons.append(create_button(
|
||||
style=ButtonStyle.blue,
|
||||
label=str(i+1),
|
||||
custom_id=custom_id,
|
||||
disabled=(board[0][i] != 0)
|
||||
))
|
||||
boards_path = "gwendolyn/resources/games/connect_four_boards/"
|
||||
file_path = f"{boards_path}board{ctx.channel_id}.png"
|
||||
image_message = await ctx.send(file=discord.File(file_path))
|
||||
|
||||
board_string = _encode_board_string(board)
|
||||
if (players[0] == self.bot.user.id):
|
||||
await self._connect_four_ai(
|
||||
ctx, board_string, players, difficulty, image_message.id
|
||||
)
|
||||
else:
|
||||
buttons = []
|
||||
for i in range(7):
|
||||
custom_id = encode_id(
|
||||
[
|
||||
"connectfour",
|
||||
"end",
|
||||
"place",
|
||||
str(players[0]),
|
||||
board_string,
|
||||
str(i),
|
||||
str(players[0]),
|
||||
str(players[1]),
|
||||
str(difficulty),
|
||||
str(image_message.id)
|
||||
]
|
||||
)
|
||||
buttons.append(create_button(
|
||||
style=ButtonStyle.red,
|
||||
label="Surrender",
|
||||
custom_id=custom_id
|
||||
style=ButtonStyle.blue,
|
||||
label=str(i+1),
|
||||
custom_id=custom_id,
|
||||
disabled=(board[0][i] != 0)
|
||||
))
|
||||
|
||||
action_rows = []
|
||||
for x in range(((len(buttons)-1)//4)+1):
|
||||
row_buttons = buttons[
|
||||
(x*4):(min(len(buttons),x*4+4))
|
||||
]
|
||||
action_rows.append(create_actionrow(*row_buttons))
|
||||
custom_id = encode_id(
|
||||
[
|
||||
"connectfour",
|
||||
"end",
|
||||
str(players[0]),
|
||||
str(players[1]),
|
||||
str(image_message.id)
|
||||
]
|
||||
)
|
||||
buttons.append(create_button(
|
||||
style=ButtonStyle.red,
|
||||
label="Surrender",
|
||||
custom_id=custom_id
|
||||
))
|
||||
|
||||
await image_message.edit(
|
||||
components=action_rows
|
||||
)
|
||||
action_rows = []
|
||||
for x in range(((len(buttons)-1)//4)+1):
|
||||
row_buttons = buttons[
|
||||
(x*4):(min(len(buttons),x*4+4))
|
||||
]
|
||||
action_rows.append(create_actionrow(*row_buttons))
|
||||
|
||||
await image_message.edit(
|
||||
components=action_rows
|
||||
)
|
||||
|
||||
async def place_piece(self, ctx: ComponentContext, board_string: str,
|
||||
column: int, players: list[int], difficulty: int,
|
||||
@ -246,7 +208,7 @@ class ConnectFour():
|
||||
user_name = self.get_name(f"#{placer}")
|
||||
placed_piece = False
|
||||
|
||||
board = self._decode_board_string(board_string)
|
||||
board = _decode_board_string(board_string)
|
||||
board = self._place_on_board(board, player_number, column)
|
||||
|
||||
if board is None:
|
||||
@ -300,7 +262,7 @@ class ConnectFour():
|
||||
if game_won:
|
||||
self._end_game(winner, players, difficulty)
|
||||
else:
|
||||
board_string = self._encode_board_string(board)
|
||||
board_string = _encode_board_string(board)
|
||||
if gwendolyn_turn:
|
||||
await self._connect_four_ai(
|
||||
ctx, board_string, players, difficulty, image_message.id
|
||||
@ -513,7 +475,7 @@ class ConnectFour():
|
||||
|
||||
self.bot.log("Figuring out best move")
|
||||
|
||||
board = self._decode_board_string(board_string)
|
||||
board = _decode_board_string(board_string)
|
||||
player = players.index(self.bot.user.id)+1
|
||||
|
||||
scores = [-math.inf for _ in range(COLUMNCOUNT)]
|
||||
@ -797,8 +759,8 @@ class DrawConnectFour():
|
||||
# pylint: enable=invalid-name
|
||||
|
||||
# Draws the whole thing
|
||||
def draw_image(self, channel: str, board: list, winner: int,
|
||||
win_coordinates: list, win_direction: str, players: list):
|
||||
def draw_image(self, channel: str, board: list, players: list,
|
||||
win_info: list):
|
||||
"""
|
||||
Draw an image of the connect four board.
|
||||
|
||||
@ -815,8 +777,8 @@ class DrawConnectFour():
|
||||
|
||||
self._draw_pieces(drawer, board)
|
||||
|
||||
if winner != 0:
|
||||
self._draw_win(background, win_coordinates, win_direction)
|
||||
if win_info[0] != 0:
|
||||
self._draw_win(background, win_info[1], win_info[2])
|
||||
|
||||
self._draw_footer(drawer, players)
|
||||
|
||||
|
Reference in New Issue
Block a user