updated unit 3 w/ resubmissions

This commit is contained in:
Rushil Umaretiya 2021-01-20 23:16:02 -05:00
parent bfd84e4f41
commit 8801b72631
5 changed files with 161 additions and 139 deletions

View File

@ -66,11 +66,114 @@ class CustomPlayer:
self.x_max = None self.x_max = None
self.y_max = None self.y_max = None
self.first_turn = True self.first_turn = True
self.color = None
def __str__(self): def __str__(self):
return "Custom Player" return "Custom Player"
def utility (self, board, color): def best_strategy(self, board, color):
# returns best move
self.x_max = len(board)
self.y_max = len(board[0])
self.color = color
v, best_move = self.alphabeta(board, color, search_depth=4, alpha=-999999999, beta=9999999)
# v, best_move = self.minimax(board, color, search_depth=4)
return (best_move // self.x_max, best_move % self.y_max), v
def minimax(self, board, color, search_depth):
return self.max_value(board, color, search_depth)
def max_value(self, board, color, search_depth):
# return value and state: (val, state)
if search_depth <= 0 or self.terminal_test(board, color):
return self.evaluate(board, self.color), board
v = -99999
result = 0
for move in self.find_moves(board, color):
max_val, max_state = self.min_value(self.make_move(board, color, move), self.opposite_color[color], search_depth - 1)
if v < max_val:
v = max_val
result = move
return v, result
def min_value(self, board, color, search_depth):
# return value and state: (val, state)
if search_depth <= 0 or self.terminal_test(board, color):
return self.evaluate(board, self.color), board
v = 999999999
result = 0
for move in self.find_moves(board, color):
min_val, min_state = self.max_value(self.make_move(board, color, move), self.opposite_color[color], search_depth - 1)
if v > min_val:
v = min_val
result = move
return v, result
def negamax(self, board, color, search_depth):
# returns best "value"
return 1
def alphabeta(self, board, color, search_depth, alpha, beta):
terminal_test = self.terminal_test(board, color)
if search_depth <= 0 or terminal_test:
if terminal_test:
for i in range(len(board)):
for j in range(len(board[i])):
if (color == self.black and board[i][j] == 'X') or (color == self.white and board[i][j] == 'O'):
move = i*self.x_max+j
if color == self.color:
return 9999, move
else:
return -9999, move
return self.evaluate(board, self.color), 0
if search_depth % 2 == 0:
v = -9999999999
result = 0
for move in self.find_moves(board, color):
max_val, max_state = self.alphabeta(self.make_move(board, color, move), self.opposite_color[color], search_depth - 1, alpha, beta)
if v < max_val:
v = max_val
result = move
if v > beta:
return v, result
alpha = max(alpha, v)
return v, result
else:
v = 9999999999
result = 0
for move in self.find_moves(board, color):
min_val, min_state = self.alphabeta(self.make_move(board, color, move), self.opposite_color[color], search_depth - 1, alpha, beta)
if v > min_val:
v = min_val
result = move
if v < alpha:
return v, result
beta = min(beta, v)
return v, result
def make_move(self, board, color, move):
successor = [x[:] for x in board]
for i in range(len(board)):
for j in range(len(board[i])):
if (color == self.black and board[i][j] == 'X') or (color == self.white and board[i][j] == 'O'):
successor[i][j] = "W"
successor[move // 5][move % 5] = 'X' if color == self.black else 'O'
return successor
def terminal_test (self, board, color):
my_moves = self.find_moves(board, color)
opponent_moves = self.find_moves(board, self.opposite_color[color])
if len(my_moves) == 0 or len(opponent_moves) == 0:
return True
else:
return False
def evaluate(self, board, color):
my_moves = len(self.find_moves(board, color)) my_moves = len(self.find_moves(board, color))
opponent_moves = len(self.find_moves(board, self.opposite_color[color])) opponent_moves = len(self.find_moves(board, self.opposite_color[color]))
if my_moves == 0 and opponent_moves == 0: if my_moves == 0 and opponent_moves == 0:
@ -82,91 +185,6 @@ class CustomPlayer:
else: else:
return my_moves - opponent_moves return my_moves - opponent_moves
def terminal_test (self, board, color):
my_moves = self.find_moves(board, color)
opponent_moves = self.find_moves(board, self.opposite_color[color])
if len(my_moves) == 0 or len(opponent_moves) == 0:
return True
else:
return False
def best_strategy(self, board, color):
# returns best move
best_move = self.minimax(board, color, 2)
return best_move
def minimax(self, board, color, search_depth):
max_val = self.max_value(board, color, search_depth) # returns state
move = self.current_position(max_val[1], color)
return (move // 5, move % 5), max_val[0]
def current_position(self, board, color):
for i in range(len(board)):
for j in range(len(board[i])):
if (color == self.black and board[i][j] == 'X') or (color == self.white and board[i][j] == 'O'):
return i*5+j
return -1
def successors(self, board, color):
successors = []
moves = self.find_moves(board, color)
current_position = self.current_position(board, color)
for move in moves:
successor = [x[:] for x in board]
if current_position != -1:
successor[current_position // 5][current_position % 5] = "W"
successor[move // 5][move % 5] = 'X' if color == self.black else 'O'
successors.append(successor)
return successors
def max_value(self, board, color, search_depth):
# return value and state: (val, state)
if search_depth <= 0 or self.terminal_test(board, color):
return self.utility(board, color), board
v = -99999
result = board
for successor in self.successors(board, color):
min_val, min_state = self.min_value(successor, self.opposite_color[color], search_depth - 1)
if v < min_val:
v = min_val
result = successor
return v, result
def min_value(self, board, color, search_depth):
# return value and state: (val, state)
if search_depth <= 0 or self.terminal_test(board, color):
return self.utility(board, self.opposite_color[color]), board
v = 99999
result = board
for successor in self.successors(board, color):
max_val, max_state = self.max_value(successor, self.opposite_color[color], search_depth - 1)
if v > max_val:
v = max_val
result = successor
return v, result
def negamax(self, board, color, search_depth):
# returns best "value"
return 1
def alphabeta(self, board, color, search_depth, alpha, beta):
# returns best "value" while also pruning
pass
def make_move(self, board, color, move):
# returns board that has been updated
return board
def evaluate(self, board, color, possible_moves):
# returns the utility value
return 1
def find_moves(self, board, color): def find_moves(self, board, color):
# finds all possible moves # finds all possible moves
possible_moves = set() possible_moves = set()
@ -182,7 +200,7 @@ class CustomPlayer:
if board[curr_x][curr_y] != '.': if board[curr_x][curr_y] != '.':
stop = True stop = True
if not stop: if not stop:
possible_moves.add(curr_x*5+curr_y) possible_moves.add(curr_x*self.y_max+curr_y)
curr_x += direction[0] curr_x += direction[0]
curr_y += direction[1] curr_y += direction[1]

View File

@ -79,6 +79,7 @@ class Best_AI_bot:
self.opposite_color = {self.black: self.white, self.white: self.black} self.opposite_color = {self.black: self.white, self.white: self.black}
self.x_max = None self.x_max = None
self.y_max = None self.y_max = None
self.color = None
self.heuristic_table = [ self.heuristic_table = [
[999,-3,2,2,2,2,-3,999], [999,-3,2,2,2,2,-3,999],
[-3,-4,-1,-1,-1,-1,-4,-3], [-3,-4,-1,-1,-1,-1,-4,-3],
@ -93,10 +94,11 @@ class Best_AI_bot:
def best_strategy(self, board, color): def best_strategy(self, board, color):
self.x_max = len(board) self.x_max = len(board)
self.y_max = len(board[0]) self.y_max = len(board[0])
self.color = color
stones_left = self.stones_left(board) stones_left = self.stones_left(board)
if stones_left > 32: if stones_left > 32:
sd = 5 sd = 4
elif stones_left > 10: elif stones_left > 10:
sd = 6 sd = 6
else: else:
@ -115,32 +117,35 @@ class Best_AI_bot:
return 1 return 1
def alphabeta(self, board, color, search_depth, alpha, beta, last_move=-1): def alphabeta(self, board, color, search_depth, alpha, beta, last_move=-1):
if search_depth <= 0 or self.terminal_test(board): terminal_test = self.terminal_test(board)
return self.evaluate(board, color, last_move), board if search_depth <= 0 or terminal_test:
if terminal_test:
return self.evaluate(board, self.color, last_move) * 1000000, last_move
return self.evaluate(board, self.color, last_move), 0
if search_depth % 2 == 0: if search_depth % 2 == 0:
v = -9999999999 v = -9999999999
result = board result = 0
for move, flipped in self.find_moves(board, color).items(): for move, flipped in self.find_moves(board, color).items():
max_val, max_state = self.alphabeta(self.make_move(board, color, move, flipped), self.opposite_color[color], search_depth - 1, alpha, beta, move) max_val, max_state = self.alphabeta(self.make_move(board, color, move, flipped), self.opposite_color[color], search_depth - 1, alpha, beta, move)
v = max (v, max_val) if v < max_val:
result = move v = max_val
result = move
if v > beta: if v > beta:
return v, result return v, result
alpha = max(alpha, v) alpha = max(alpha, v)
return v, result return v, result
else: else:
v = 9999999999 v = 9999999999
result = board result = 0
for move, flipped in self.find_moves(board, color).items(): for move, flipped in self.find_moves(board, color).items():
min_val, min_state = self.alphabeta(self.make_move(board, color, move, flipped), self.opposite_color[color], search_depth - 1, alpha, beta, move) min_val, min_state = self.alphabeta(self.make_move(board, color, move, flipped), self.opposite_color[color], search_depth - 1, alpha, beta, move)
v = min (v, min_val) if v > min_val:
result = move v = min_val
result = move
if v < alpha: if v < alpha:
return v, result return v, result
beta = max(beta, v) beta = min(beta, v)
return v, result return v, result
def terminal_test(self, board): def terminal_test(self, board):
@ -168,7 +173,7 @@ class Best_AI_bot:
return my_board return my_board
def evaluate(self, board, color, last_move, possible_moves=[]): def evaluate(self, board, color, last_move):
score = self.score(board, color) score = self.score(board, color)
if last_move != -1: if last_move != -1:
heuristic = self.heuristic_table[last_move // self.x_max][last_move % self.y_max] heuristic = self.heuristic_table[last_move // self.x_max][last_move % self.y_max]

View File

@ -63,45 +63,44 @@ class SmartBot:
self.color = color self.color = color
sd = 4 sd = 4
v, best_move = self.alphabeta(board, color, sd, 9999999999, 9999999999) # returns state v, best_move = self.alphabeta(board, color, sd, -9999999999, 9999999999) # returns state
return best_move, v return best_move, v
def alphabeta(self, board, color, search_depth, alpha, beta): def alphabeta(self, board, color, search_depth, alpha, beta, last_move = -1):
terminal_test = self.terminal_test(board, color) terminal_test = self.terminal_test(board, color)
if search_depth <= 0 or terminal_test: if search_depth <= 0 or terminal_test:
if terminal_test: if terminal_test:
if color == self.color: if color == self.color:
return 99999999, board return 99999999, last_move
else: else:
return -99999999, board return -99999999, last_move
heuristic = self.evaluate(board, color) heuristic = self.evaluate(board, color)
print("I'm seeing a heuristic of: ", heuristic) return heuristic, 0
return heuristic, board
if search_depth % 2 == 0: if search_depth % 2 == 0:
v = -9999999999 v = -9999999999
result = board result = None
for move in self.find_moves(board, color): for move in self.find_moves(board, color):
max_val, max_state = self.alphabeta(self.make_move(board, color, move), self.opposite_color[color], search_depth - 1, alpha, beta) max_val, max_state = self.alphabeta(self.make_move(board, color, move), self.opposite_color[color], search_depth - 1, alpha, beta, move)
v = max (v, max_val) if max_val > v:
result = move v = max_val
result = move
if v > beta: if v > beta:
return v, result return v, result
alpha = max(alpha, v) alpha = max(alpha, v)
return v, result return v, result
else: else:
v = 9999999999 v = 9999999999
result = board result = None
for move in self.find_moves(board, color): for move in self.find_moves(board, color):
min_val, min_state = self.alphabeta(self.make_move(board, color, move), self.opposite_color[color], search_depth - 1, alpha, beta) min_val, min_state = self.alphabeta(self.make_move(board, color, move), self.opposite_color[color], search_depth - 1, alpha, beta, move)
v = min (v, min_val) if min_val < v:
result = move v = min_val
result = move
if v < alpha: if v < alpha:
return v, result return v, result
beta = max(beta, v) beta = min(beta, v)
return v, result return v, result
def minimax(self, board, color, search_depth): def minimax(self, board, color, search_depth):
@ -115,11 +114,6 @@ class SmartBot:
def make_move(self, board, color, move): def make_move(self, board, color, move):
my_board = [row[:] for row in board] my_board = [row[:] for row in board]
if color == "#ffff00":
color = "O"
else:
color = "X"
my_board[move[0]][move[1]] = color my_board[move[0]][move[1]] = color
return my_board return my_board

View File

@ -9,7 +9,7 @@ import time
import tkinter as tk import tkinter as tk
# Change the following line # Change the following line
from Umaretiya_r_U3_L3_testing import RandomBot, Best_AI_bot from Umaretiya_r_U3_L3 import RandomBot, Best_AI_bot
# constants # constants
delay_time = 0 delay_time = 0

View File

@ -188,13 +188,14 @@ INSULTS = [
class Strategy: class Strategy:
def __init__(self): def __init__(self):
self.logging = True #self.logging = True
self.white = "o" self.white = "o"
self.black = "x" self.black = "x"
self.directions = [[-1, -1], [-1, 0], [-1, 1], [0, -1], [0, 1], [1, -1], [1, 0], [1, 1]] self.directions = [[-1, -1], [-1, 0], [-1, 1], [0, -1], [0, 1], [1, -1], [1, 0], [1, 1]]
self.opposite_color = {self.black: self.white, self.white: self.black} self.opposite_color = {self.black: self.white, self.white: self.black}
self.x_max = None self.x_max = None
self.y_max = None self.y_max = None
self.color = None
self.heuristic_table = [ self.heuristic_table = [
[999,-3,2,2,2,2,-3,999], [999,-3,2,2,2,2,-3,999],
[-3,-4,-1,-1,-1,-1,-4,-3], [-3,-4,-1,-1,-1,-1,-4,-3],
@ -219,10 +220,11 @@ class Strategy:
board_arr = self.setup_board(board) board_arr = self.setup_board(board)
self.x_max = len(board_arr) self.x_max = len(board_arr)
self.y_max = len(board_arr[0]) self.y_max = len(board_arr[0])
self.color = player
stones_left = self.stones_left(board_arr) stones_left = self.stones_left(board)
if stones_left > 32: if stones_left > 32:
sd = 5 sd = 6
elif stones_left > 10: elif stones_left > 10:
sd = 6 sd = 6
else: else:
@ -244,32 +246,35 @@ class Strategy:
return 1 return 1
def alphabeta(self, board, color, search_depth, alpha, beta, last_move=-1): def alphabeta(self, board, color, search_depth, alpha, beta, last_move=-1):
if search_depth <= 0 or self.terminal_test(board): terminal_test = self.terminal_test(board)
return self.evaluate(board, color, last_move), board if search_depth <= 0 or terminal_test:
if terminal_test:
return self.evaluate(board, self.color, last_move) * 1000000, last_move
return self.evaluate(board, self.color, last_move), 0
if search_depth % 2 == 0: if search_depth % 2 == 0:
v = -9999999999 v = -9999999999
result = board result = 0
for move, flipped in self.find_moves(board, color).items(): for move, flipped in self.find_moves(board, color).items():
max_val, max_state = self.alphabeta(self.make_move(board, color, move, flipped), self.opposite_color[color], search_depth - 1, alpha, beta, move) max_val, max_state = self.alphabeta(self.make_move(board, color, move, flipped), self.opposite_color[color], search_depth - 1, alpha, beta, move)
v = max (v, max_val) if v < max_val:
result = move v = max_val
result = move
if v > beta: if v > beta:
return v, result return v, result
alpha = max(alpha, v) alpha = max(alpha, v)
return v, result return v, result
else: else:
v = 9999999999 v = 9999999999
result = board result = 0
for move, flipped in self.find_moves(board, color).items(): for move, flipped in self.find_moves(board, color).items():
min_val, min_state = self.alphabeta(self.make_move(board, color, move, flipped), self.opposite_color[color], search_depth - 1, alpha, beta, move) min_val, min_state = self.alphabeta(self.make_move(board, color, move, flipped), self.opposite_color[color], search_depth - 1, alpha, beta, move)
v = min (v, min_val) if v > min_val:
result = move v = min_val
result = move
if v < alpha: if v < alpha:
return v, result return v, result
beta = max(beta, v) beta = min(beta, v)
return v, result return v, result
def terminal_test(self, board): def terminal_test(self, board):
@ -297,7 +302,7 @@ class Strategy:
return my_board return my_board
def evaluate(self, board, color, last_move, possible_moves=[]): def evaluate(self, board, color, last_move):
score = self.score(board, color) score = self.score(board, color)
if last_move != -1: if last_move != -1:
heuristic = self.heuristic_table[last_move // self.x_max][last_move % self.y_max] heuristic = self.heuristic_table[last_move // self.x_max][last_move % self.y_max]