aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bot/exts/evergreen/tic_tac_toe.py47
1 files changed, 47 insertions, 0 deletions
diff --git a/bot/exts/evergreen/tic_tac_toe.py b/bot/exts/evergreen/tic_tac_toe.py
index a9971ad2..b306e803 100644
--- a/bot/exts/evergreen/tic_tac_toe.py
+++ b/bot/exts/evergreen/tic_tac_toe.py
@@ -1,4 +1,5 @@
import asyncio
+import random
import typing as t
import discord
@@ -44,6 +45,52 @@ class Player:
return False, list(Emojis.number_emojis.keys())[list(Emojis.number_emojis.values()).index(react.emoji)]
+class AI:
+ """Tic Tac Toe AI class for against computer gaming."""
+
+ def __init__(self, symbol: str):
+ self.symbol = symbol
+
+ async def check_win(self, board: t.Dict[int, str]) -> bool:
+ """Check does this move will result game end."""
+ if (
+ # Horizontal
+ board[1] == board[2] == board[3]
+ or board[4] == board[5] == board[6]
+ or board[7] == board[8] == board[9]
+ # Vertical
+ or board[1] == board[4] == board[7]
+ or board[2] == board[5] == board[8]
+ or board[3] == board[6] == board[9]
+ # Diagonal
+ or board[1] == board[5] == board[9]
+ or board[3] == board[5] == board[7]
+ ):
+ return True
+ return False
+
+ async def get_move(self, board: t.Dict[int, str], _: discord.Message) -> t.Tuple[bool, int]:
+ """Get move from AI. AI use Minimax strategy."""
+ possible_moves = [i for i, emoji in board.items() if emoji in Emojis.number_emojis]
+
+ for symbol in (Emojis.x, Emojis.o):
+ for move in possible_moves:
+ board_copy = board.copy()
+ board_copy[move] = symbol
+ if self.check_win(board_copy):
+ return False, move
+
+ open_corners = [i for i in possible_moves if i in (1, 3, 7, 9)]
+ if len(open_corners) > 0:
+ return False, random.choice(open_corners)
+
+ if 5 in possible_moves:
+ return False, 5
+
+ open_edges = [i for i in possible_moves if i in (2, 4, 6, 8)]
+ return False, random.choice(open_edges)
+
+
class Game:
"""Class that contains information and functions about Tic Tac Toe game."""