-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathplayer_vs_model.py
117 lines (87 loc) · 3.15 KB
/
player_vs_model.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
from keras.api.models import load_model, Model
import chess
import numpy as np
from tqdm import tqdm
from src.utils.encoding_utils import encode_board
model: Model = load_model('models/model.keras')
# Cache for legal moves
legal_moves_cache = {}
# Transposition table
transposition_table = {}
def get_legal_moves(board: chess.Board):
board_key = board.fen()
if board_key in legal_moves_cache:
return legal_moves_cache[board_key]
legal_moves = list(board.legal_moves)
legal_moves_cache[board_key] = legal_moves
return legal_moves
def evaluate_board(board: chess.Board):
encoded_board = encode_board(board)
encoded_board = np.reshape(encoded_board, (1, 8, 8, 12))
prediction = model.predict(encoded_board, verbose=0, batch_size=1)
return prediction[0][0]
def minimax(board: chess.Board, depth: int, alpha: float, beta, maximizing_player: bool):
if depth == 0 or board.is_game_over():
return evaluate_board(board)
legal_moves = get_legal_moves(board)
if maximizing_player:
max_eval = float('-inf')
for move in legal_moves:
board.push(move)
evaluation = minimax(board, depth - 1, alpha, beta, False)
board.pop()
max_eval = max(max_eval, evaluation)
alpha = max(alpha, evaluation)
if beta <= alpha:
break
return max_eval
min_eval = float('inf')
for move in legal_moves:
board.push(move)
evaluation = minimax(board, depth - 1, alpha, beta, True)
board.pop()
min_eval = min(min_eval, evaluation)
beta = min(beta, evaluation)
if beta <= alpha:
break
return min_eval
def minimax_root(board: chess.Board, depth: int, maximizing_player: bool):
best_move = None
best_eval = float('-inf') if maximizing_player else float('inf')
legal_moves = get_legal_moves(board)
for move in tqdm(legal_moves, desc="Finding best move", ascii=True, leave=True):
board.push(move)
evaluation = minimax(board, depth - 1, float('-inf'),
float('inf'), not maximizing_player)
board.pop()
if maximizing_player and evaluation > best_eval:
best_eval = evaluation
best_move = move
elif not maximizing_player and evaluation < best_eval:
best_eval = evaluation
best_move = move
return best_move
def minimax_move(board: chess.Board, depth: int):
return minimax_root(board, depth, board.turn)
def main():
board = chess.Board()
while not board.is_game_over(claim_draw=True):
if board.turn:
move = minimax_move(board, 3)
else:
move = input('Enter your move: ')
while chess.Move.from_uci(move) not in get_legal_moves(board):
move = input('Enter a legal move: ')
move = chess.Move.from_uci(move)
board.push(move)
print("===")
print(board.result())
print("===")
print(f"fen: {board.fen()}")
print("===")
print(board)
print("===")
for move in board.move_stack:
print(move, end=' ')
if __name__ == '__main__':
main()