-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathplay.py
139 lines (109 loc) · 3.81 KB
/
play.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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
from model import ChessModel
import torch
import sys
import chess
def load_model(path):
try:
vals = torch.load(path, weights_only=True)
model = ChessModel()
model.load_state_dict(vals)
return model
except Exception as e:
print(f"Error loading AI model: {e}")
sys.exit()
def handcrafted_evaluate(s):
piece_values = {
chess.PAWN: 1,
chess.KNIGHT: 3,
chess.BISHOP: 3,
chess.ROOK: 5,
chess.QUEEN: 9,
chess.KING: 0
}
score = 0
for piece_type in piece_values:
score += len(s.board.pieces(piece_type, chess.WHITE)) * piece_values[piece_type]
score -= len(s.board.pieces(piece_type, chess.BLACK)) * piece_values[piece_type]
return score
def model_evaluate(s, model):
b = s.board_to_matrix()
input_tensor = torch.tensor(b, dtype=torch.float32).unsqueeze(0)
with torch.no_grad():
output = model(input_tensor)
return output.item()
def combined_evaluate(s, model):
model_score = model_evaluate(s, model)
handcrafted_score = handcrafted_evaluate(s)
combined_score = model_score + handcrafted_score
return combined_score
def human_move(selected_square, square, s):
if selected_square is None:
piece = s.board.piece_at(square)
if piece and piece.color == chess.BLACK:
selected_square = square
return s, selected_square, False, None
else:
move = chess.Move(selected_square, square)
if chess.square_rank(square) == 0 and s.board.piece_at(selected_square).symbol() == 'p': # if promotion square
pieces_to_nums = {"q":5, "k":2, "r":4, "b":3}
while True:
print("Promote to: q (Queen), k (Knight), b (Bishop), r (Rook)")
ans = input()
if ans in "qkbr":
move = chess.Move(selected_square, square, pieces_to_nums[ans])
print(move)
break
if move in s.board.legal_moves:
s.board.push(move)
return s, None, True, move
else:
print("Invalid move")
return s, None, False, None
# int alphaBetaMax( int alpha, int beta, int depthleft ) {
# if ( depthleft == 0 ) return evaluate();
# bestValue = -infinity;
# for ( all moves) {
# score = alphaBetaMin( alpha, beta, depthleft - 1 );
# if( score > bestValue )
# {
# bestValue = alpha;
# if( score > alpha )
# alpha = score; // alpha acts like max in MiniMax
# }
# if( score >= beta )
# return score; // fail soft beta-cutoff
# }
# return bestValue;
# }
def alphaBetaMax(depth, s, alpha, beta, maxPlayer, model):
if depth == 0 or s.board.is_game_over():
return combined_evaluate(s, model), None
bestMove = None
if maxPlayer:
bestScore = -float('inf')
for move in s.board.legal_moves:
s.board.push(move)
score, m = alphaBetaMax(depth-1, s, alpha, beta, False, model)
s.board.pop()
if score > bestScore:
bestScore = score
bestMove = move
if score > alpha:
alpha = score
if alpha >= beta:
break
return bestScore, bestMove
else:
bestScore = float('inf')
for move in s.board.legal_moves:
s.board.push(move)
score, m = alphaBetaMax(depth-1, s, alpha, beta, True, model)
s.board.pop()
if score < bestScore:
bestScore = score
bestMove = move
if score < beta:
beta = score
if alpha >= beta:
break
return bestScore, bestMove