From 8801b72631229b11fca87e8e84ee9619b0735c08 Mon Sep 17 00:00:00 2001 From: Rushil Umaretiya Date: Wed, 20 Jan 2021 23:16:02 -0500 Subject: [PATCH] updated unit 3 w/ resubmissions --- Unit 3/Umaretiya_r_U3_L2.py | 192 ++++++++++++++----------- Unit 3/Umaretiya_r_U3_L3.py | 31 ++-- Unit 3/connect_4/Umaretiya_r_player.py | 40 +++--- Unit 3/othello_runner.py | 2 +- Unit 3/othello_submission.py | 35 +++-- 5 files changed, 161 insertions(+), 139 deletions(-) diff --git a/Unit 3/Umaretiya_r_U3_L2.py b/Unit 3/Umaretiya_r_U3_L2.py index fc8a385..0b6a4cd 100644 --- a/Unit 3/Umaretiya_r_U3_L2.py +++ b/Unit 3/Umaretiya_r_U3_L2.py @@ -66,11 +66,114 @@ class CustomPlayer: self.x_max = None self.y_max = None self.first_turn = True + self.color = None def __str__(self): 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)) opponent_moves = len(self.find_moves(board, self.opposite_color[color])) if my_moves == 0 and opponent_moves == 0: @@ -81,91 +184,6 @@ class CustomPlayer: return 1000 else: 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): # finds all possible moves @@ -182,7 +200,7 @@ class CustomPlayer: if board[curr_x][curr_y] != '.': stop = True 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_y += direction[1] diff --git a/Unit 3/Umaretiya_r_U3_L3.py b/Unit 3/Umaretiya_r_U3_L3.py index 6e22076..296919e 100644 --- a/Unit 3/Umaretiya_r_U3_L3.py +++ b/Unit 3/Umaretiya_r_U3_L3.py @@ -79,6 +79,7 @@ class Best_AI_bot: self.opposite_color = {self.black: self.white, self.white: self.black} self.x_max = None self.y_max = None + self.color = None self.heuristic_table = [ [999,-3,2,2,2,2,-3,999], [-3,-4,-1,-1,-1,-1,-4,-3], @@ -93,10 +94,11 @@ class Best_AI_bot: def best_strategy(self, board, color): self.x_max = len(board) self.y_max = len(board[0]) + self.color = color stones_left = self.stones_left(board) if stones_left > 32: - sd = 5 + sd = 4 elif stones_left > 10: sd = 6 else: @@ -115,32 +117,35 @@ class Best_AI_bot: return 1 def alphabeta(self, board, color, search_depth, alpha, beta, last_move=-1): - if search_depth <= 0 or self.terminal_test(board): - return self.evaluate(board, color, last_move), board + terminal_test = self.terminal_test(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: v = -9999999999 - result = board + result = 0 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) - v = max (v, max_val) - result = move + 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 = board + result = 0 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) - v = min (v, min_val) - result = move + if v > min_val: + v = min_val + result = move if v < alpha: return v, result - beta = max(beta, v) - + beta = min(beta, v) return v, result def terminal_test(self, board): @@ -168,7 +173,7 @@ class Best_AI_bot: return my_board - def evaluate(self, board, color, last_move, possible_moves=[]): + def evaluate(self, board, color, last_move): score = self.score(board, color) if last_move != -1: heuristic = self.heuristic_table[last_move // self.x_max][last_move % self.y_max] diff --git a/Unit 3/connect_4/Umaretiya_r_player.py b/Unit 3/connect_4/Umaretiya_r_player.py index 5c32a94..5cc06a1 100644 --- a/Unit 3/connect_4/Umaretiya_r_player.py +++ b/Unit 3/connect_4/Umaretiya_r_player.py @@ -63,45 +63,44 @@ class SmartBot: self.color = color 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 - 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) if search_depth <= 0 or terminal_test: if terminal_test: if color == self.color: - return 99999999, board + return 99999999, last_move else: - return -99999999, board + return -99999999, last_move heuristic = self.evaluate(board, color) - print("I'm seeing a heuristic of: ", heuristic) - return heuristic, board - + return heuristic, 0 + if search_depth % 2 == 0: v = -9999999999 - result = board + result = None 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) - v = max (v, max_val) - result = move + max_val, max_state = self.alphabeta(self.make_move(board, color, move), self.opposite_color[color], search_depth - 1, alpha, beta, move) + if max_val > v: + v = max_val + result = move if v > beta: return v, result alpha = max(alpha, v) - return v, result else: v = 9999999999 - result = board + result = None 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) - v = min (v, min_val) - result = move + min_val, min_state = self.alphabeta(self.make_move(board, color, move), self.opposite_color[color], search_depth - 1, alpha, beta, move) + if min_val < v: + v = min_val + result = move if v < alpha: return v, result - beta = max(beta, v) - + beta = min(beta, v) return v, result def minimax(self, board, color, search_depth): @@ -115,11 +114,6 @@ class SmartBot: def make_move(self, board, color, move): my_board = [row[:] for row in board] - if color == "#ffff00": - color = "O" - else: - color = "X" - my_board[move[0]][move[1]] = color return my_board diff --git a/Unit 3/othello_runner.py b/Unit 3/othello_runner.py index 92432aa..ac71cd7 100644 --- a/Unit 3/othello_runner.py +++ b/Unit 3/othello_runner.py @@ -9,7 +9,7 @@ import time import tkinter as tk # 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 delay_time = 0 diff --git a/Unit 3/othello_submission.py b/Unit 3/othello_submission.py index 0ff6b8f..8a68d20 100644 --- a/Unit 3/othello_submission.py +++ b/Unit 3/othello_submission.py @@ -188,13 +188,14 @@ INSULTS = [ class Strategy: def __init__(self): - self.logging = True + #self.logging = True self.white = "o" self.black = "x" 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.x_max = None self.y_max = None + self.color = None self.heuristic_table = [ [999,-3,2,2,2,2,-3,999], [-3,-4,-1,-1,-1,-1,-4,-3], @@ -219,10 +220,11 @@ class Strategy: board_arr = self.setup_board(board) self.x_max = len(board_arr) 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: - sd = 5 + sd = 6 elif stones_left > 10: sd = 6 else: @@ -244,32 +246,35 @@ class Strategy: return 1 def alphabeta(self, board, color, search_depth, alpha, beta, last_move=-1): - if search_depth <= 0 or self.terminal_test(board): - return self.evaluate(board, color, last_move), board + terminal_test = self.terminal_test(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: v = -9999999999 - result = board + result = 0 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) - v = max (v, max_val) - result = move + 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 = board + result = 0 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) - v = min (v, min_val) - result = move + if v > min_val: + v = min_val + result = move if v < alpha: return v, result - beta = max(beta, v) - + beta = min(beta, v) return v, result def terminal_test(self, board): @@ -297,7 +302,7 @@ class Strategy: return my_board - def evaluate(self, board, color, last_move, possible_moves=[]): + def evaluate(self, board, color, last_move): score = self.score(board, color) if last_move != -1: heuristic = self.heuristic_table[last_move // self.x_max][last_move % self.y_max]