Can you please explain to me why my AI can play properly, until player has 3 in a row in sixth or seventh column then my AI refuses to block him. And another problem is in a position when my AI can win in 1 move, but he will rather choose a longer game. Can anyone help me please.
Returns a value for a winning move
def utility(board):
if terminal(board):
if winning_move(board, X):
return 1000000
elif winning_move(board, O):
return -10000
else:
return 0
Calculates the score of position when depth = 0
def compute_score(block, board, col, row):
score = 0
if block.count(X) == 4 and block.count("-") == 0:
score += 100000
elif block.count(X) == 3 and block.count("-") == 1:
score += 10
elif block.count(X) == 2 and block.count("-") == 2:
score += 3
if block.count(O) == 4 and block.count("-") == 0:
score -= 1000000
elif block.count(O) == 3 and block.count("-") == 1:
score -= 6
elif block.count(O) == 2 and block.count("-") == 2:
score -= 2
return score
Gives value to every possible "four block"
def score_position(board):
score = 0
mid_section = []
#increases score because playing in middle is usually good move
for col in range(5):
mid_section.append(board[col][x // 2])
score += mid_section.count(X) * 3
#claculates score of all horizontal 4 in a rows
for row in range(y):
for col in range(x - 3):
block = board[col: col + 4]
score += compute_score(block, board, col, row)
#claculates score of all vertical 4 in a rows
for col in range(x):
for row in range(y - 3):
block = [board[row][col], board[row + 1][col], board[row + 2][col], board[row + 3][col]]
score += compute_score(block, board, col, row)
#claculates score of all diagonals from left bottom to right top 4 in a rows
for row in range(y - 3):
for col in range(x - 3):
block = [board[row][col], board[row + 1][col + 1], board[row + 2][col + 2], board[row + 3][col + 3]]
score += compute_score(block, board, col, row)
#claculates score of all diagonals from right bottom to left top 4 in a rows
for row in range(y - 3):
for col in range(x - 1, 2, -1):
block = [board[row][col], board[row + 1][col - 1], board[row + 2][col - 2], board[row + 3][col - 3]]
score += compute_score(block, board, col, row)
return score
The minimax algorithm (if you want to know more about this algorithm check this video - https://www.youtube.com/watch?v=l-hh51ncgDI)
def minimax(board, depth):
#if terminal(board):
# return None
best_move = None
alpha = -math.inf
beta = math.inf
if player(board) == X:
if board == initial_state():
best_move = x//2
return best_move
best_score = -math.inf
for action in actions(board):
score = minimaze(result(board, action), alpha, beta, depth)
alpha = max(alpha, score)
if score > best_score:
best_score = score
best_move = action
return best_move
else:
best_score = math.inf
for action in actions(board):
score = maximaze(result(board, action), alpha, beta, depth)
beta = min(beta, score)
if score < best_score:
best_score = score
best_move = action
print(best_move)
return best_move
The minimazing player (returns the best player move four the specific position)
def minimaze(board, alpha, beta, depth):
if terminal(board):
return utility(board)
elif depth <= 0:
return score_position(board)
v = math.inf
for action in actions(board):
v = min(v, maximaze(result(board, action), alpha, beta, depth - 1))
beta = min(beta, v)
return v
The maximazing AI (returns the best AI move four the specific position)
def maximaze(board, alpha, beta, depth):
if terminal(board):
return utility(board)
elif depth <= 0:
return score_position(board)
v = -math.inf
for action in actions(board):
v = max(v, minimaze(result(board, action), alpha, beta, depth - 1))
alpha = max(alpha, v)
return v