Last active
July 11, 2023 18:42
-
-
Save estebanthi/80c5fe48715e74fced5220f44ad43f9a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import chess | |
import random | |
import chess.svg | |
def random_move(board): | |
moves = list(board.legal_moves) | |
move = random.choice(moves) | |
return move | |
piece_values = { | |
chess.PAWN: 1, | |
chess.KNIGHT: 3, | |
chess.BISHOP: 3, | |
chess.ROOK: 5, | |
chess.QUEEN: 9, | |
chess.KING: 0 | |
} | |
def evaluate_board(board): | |
score = 0 | |
for square in chess.SQUARES: | |
piece = board.piece_at(square) | |
if piece is not None: | |
if piece.color == chess.WHITE: | |
score += piece_values[piece.piece_type] | |
else: | |
score -= piece_values[piece.piece_type] | |
return score | |
def try_evaluation_function(): | |
board = chess.Board() | |
evaluation = evaluate_board(board) | |
print(f"Evaluation with all pieces: {evaluation}") | |
# remove a white pawn | |
board.remove_piece_at(chess.E2) | |
evaluation = evaluate_board(board) | |
print(f"Evaluation without a white pawn: {evaluation}") | |
# remove a black rook | |
board.remove_piece_at(chess.A8) | |
evaluation = evaluate_board(board) | |
print(f"Evaluation without a black rook: {evaluation}") | |
def best_move_using_simple_evaluation(board): | |
white_to_play = board.turn | |
best_score = -99999 if white_to_play else 99999 | |
best_move = random_move(board) | |
for move in board.legal_moves: | |
board.push(move) | |
score = evaluate_board(board) | |
board.pop() | |
if score > best_score and white_to_play: | |
best_score = score | |
best_move = move | |
elif score < best_score and not white_to_play: | |
best_score = score | |
best_move = move | |
return best_move | |
def minimax_without_alpha_beta_pruning(board, depth, white_to_play): | |
if depth == 0 or board.is_game_over(): | |
return evaluate_board(board) | |
if white_to_play: | |
best_score = -99999 | |
for move in board.legal_moves: | |
board.push(move) | |
score = minimax_without_alpha_beta_pruning(board, depth - 1, False) | |
board.pop() | |
best_score = max(score, best_score) | |
return best_score | |
else: | |
best_score = 99999 | |
for move in board.legal_moves: | |
board.push(move) | |
score = minimax_without_alpha_beta_pruning(board, depth - 1, True) | |
board.pop() | |
best_score = min(score, best_score) | |
return best_score | |
def best_move_using_minimax_without_alpha_beta_pruning(board, depth): | |
white_to_play = board.turn | |
best_score = -99999 if white_to_play else 99999 | |
best_move = random_move(board) | |
for move in board.legal_moves: | |
board.push(move) | |
score = minimax_without_alpha_beta_pruning(board, depth - 1, not white_to_play) | |
board.pop() | |
if score > best_score and white_to_play: | |
best_score = score | |
best_move = move | |
elif score < best_score and not white_to_play: | |
best_score = score | |
best_move = move | |
return best_move | |
def minimax_with_alpha_beta_pruning(board, depth, alpha, beta, white_to_play): | |
if depth == 0 or board.is_game_over(): | |
return evaluate_board(board) | |
if white_to_play: | |
best_score = -99999 | |
for move in board.legal_moves: | |
board.push(move) | |
score = minimax_with_alpha_beta_pruning(board, depth - 1, alpha, beta, False) | |
board.pop() | |
best_score = max(score, best_score) | |
alpha = max(alpha, score) | |
if alpha >= beta: | |
break | |
return best_score | |
else: | |
best_score = 99999 | |
for move in board.legal_moves: | |
board.push(move) | |
score = minimax_with_alpha_beta_pruning(board, depth - 1, alpha, beta, True) | |
board.pop() | |
best_score = min(score, best_score) | |
beta = min(beta, score) | |
if alpha >= beta: | |
break | |
return best_score | |
def best_move_using_minimax_with_alpha_beta_pruning(board, depth): | |
white_to_play = board.turn | |
best_score = -99999 if white_to_play else 99999 | |
best_moves = [] | |
for move in board.legal_moves: | |
board.push(move) | |
score = minimax_with_alpha_beta_pruning(board, depth - 1, -99999, 99999, not white_to_play) | |
board.pop() | |
if score >= best_score and white_to_play: | |
if len(best_moves) > 0 and score > best_score: | |
best_moves.clear() | |
best_score = score | |
best_moves.append(move) | |
elif score <= best_score and not white_to_play: | |
if len(best_moves) > 0 and score < best_score: | |
best_moves.clear() | |
best_score = score | |
best_moves.append(move) | |
return random.choice(best_moves) | |
piece_values_with_position = { | |
chess.PAWN: [ | |
[0, 0, 0, 0, 0, 0, 0, 0], | |
[50, 50, 50, 50, 50, 50, 50, 50], | |
[10, 10, 20, 30, 30, 20, 10, 10], | |
[5, 5, 10, 25, 25, 10, 5, 5], | |
[0, 0, 0, 20, 20, 0, 0, 0], | |
[5, -5, -10, 0, 0, -10, -5, 5], | |
[5, 10, 10, -20, -20, 10, 10, 5], | |
[0, 0, 0, 0, 0, 0, 0, 0] | |
], | |
chess.KNIGHT: [ | |
[-50, -40, -30, -30, -30, -30, -40, -50], | |
[-40, -20, 0, 0, 0, 0, -20, -40], | |
[-30, 0, 10, 15, 15, 10, 0, -30], | |
[-30, 5, 15, 20, 20, 15, 5, -30], | |
[-30, 0, 15, 20, 20, 15, 0, -30], | |
[-30, 5, 10, 15, 15, 10, 5, -30], | |
[-40, -20, 0, 5, 5, 0, -20, -40], | |
[-50, -40, -30, -30, -30, -30, -40, -50] | |
], | |
chess.BISHOP: [ | |
[-20, -10, -10, -10, -10, -10, -10, -20], | |
[-10, 0, 0, 0, 0, 0, 0, -10], | |
[-10, 0, 5, 10, 10, 5, 0, -10], | |
[-10, 5, 5, 10, 10, 5, 5, -10], | |
[-10, 0, 10, 10, 10, 10, 0, -10], | |
[-10, 10, 10, 10, 10, 10, 10, -10], | |
[-10, 5, 0, 0, 0, 0, 5, -10], | |
[-20, -10, -10, -10, -10, -10, -10, -20] | |
], | |
chess.ROOK: [ | |
[0, 0, 0, 0, 0, 0, 0, 0], | |
[5, 10, 10, 10, 10, 10, 10, 5], | |
[-5, 0, 0, 0, 0, 0, 0, -5], | |
[-5, 0, 0, 0, 0, 0, 0, -5], | |
[-5, 0, 0, 0, 0, 0, 0, -5], | |
[-5, 0, 0, 0, 0, 0, 0, -5], | |
[-5, 0, 0, 0, 0, 0, 0, -5], | |
[0, 0, 0, 5, 5, 0, 0, 0] | |
], | |
chess.QUEEN: [ | |
[-20, -10, -10, -5, -5, -10, -10, -20], | |
[-10, 0, 0, 0, 0, 0, 0, -10], | |
[-10, 0, 5, 5, 5, 5, 0, -10], | |
[-5, 0, 5, 5, 5, 5, 0, -5], | |
[0, 0, 5, 5, 5, 5, 0, -5], | |
[-10, 5, 5, 5, 5, 5, 0, -10], | |
[-10, 0, 5, 0, 0, 0, 0, -10], | |
[-20, -10, -10, -5, -5, -10, -10, -20] | |
], | |
chess.KING: [ | |
[-30, -40, -40, -50, -50, -40, -40, -30], | |
[-30, -40, -40, -50, -50, -40, -40, -30], | |
[-30, -40, -40, -50, -50, -40, -40, -30], | |
[-30, -40, -40, -50, -50, -40, -40, -30], | |
[-20, -30, -30, -40, -40, -30, -30, -20], | |
[-10, -20, -20, -20, -20, -20, -20, -10], | |
[20, 20, 0, 0, 0, 0, 20, 20], | |
[20, 30, 10, 0, 0, 10, 30, 20] | |
] | |
} | |
def get_piece_value(piece, x, y): | |
if piece.piece_type == chess.PAWN: | |
return 100 + piece_values_with_position[piece.piece_type][x][y] | |
elif piece.piece_type == chess.KNIGHT: | |
return 320 + piece_values_with_position[piece.piece_type][x][y] | |
elif piece.piece_type == chess.BISHOP: | |
return 330 + piece_values_with_position[piece.piece_type][x][y] | |
elif piece.piece_type == chess.ROOK: | |
return 500 + piece_values_with_position[piece.piece_type][x][y] | |
elif piece.piece_type == chess.QUEEN: | |
return 900 + piece_values_with_position[piece.piece_type][x][y] | |
elif piece.piece_type == chess.KING: | |
return 20000 + piece_values_with_position[piece.piece_type][x][y] | |
else: | |
return 0 | |
def evaluate_board(board): | |
score = 0 | |
for i in range(8): | |
for j in range(8): | |
piece = board.piece_at(chess.square(i, j)) | |
if piece is not None: | |
if piece.color == chess.WHITE: | |
score += get_piece_value(piece, i, j) | |
else: | |
score -= get_piece_value(piece, i, j) | |
return score | |
if __name__ == "__main__": | |
white_wins = 0 | |
black_wins = 0 | |
draws = 0 | |
n = 10 | |
depth = 3 | |
for i in range(n): | |
board = chess.Board() | |
while not board.is_game_over(): | |
print("White to move" if board.turn else "Black to move") | |
if board.turn == chess.WHITE: | |
move = best_move_using_minimax_with_alpha_beta_pruning(board, depth) | |
board.push(move) | |
else: | |
move = best_move_using_minimax_with_alpha_beta_pruning(board, depth) | |
board.push(move) | |
print(board) | |
print() | |
if board.result() == "1-0": | |
white_wins += 1 | |
elif board.result() == "0-1": | |
black_wins += 1 | |
else: | |
draws += 1 | |
print(f"Game {i+1} finished, result: {board.result()}") | |
print(f"White winrate: {white_wins/n * 100}%") | |
print(f"Black winrate: {black_wins/n * 100}%") | |
print(f"Draw rate: {draws/n * 100}%") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment