mirror of
https://github.com/Rushilwiz/AI.git
synced 2025-04-16 09:00:18 -04:00
updated unit 3 w/ resubmissions
This commit is contained in:
parent
bfd84e4f41
commit
8801b72631
|
@ -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:
|
||||
|
@ -82,91 +185,6 @@ class CustomPlayer:
|
|||
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
|
||||
possible_moves = set()
|
||||
|
@ -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]
|
||||
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]
|
||||
|
|
Loading…
Reference in New Issue
Block a user