-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathChessAI.py
More file actions
131 lines (114 loc) · 5.07 KB
/
ChessAI.py
File metadata and controls
131 lines (114 loc) · 5.07 KB
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
"""
Handling the AI moves.
"""
import random
piece_score = {"K": 0, "Q": 9, "R": 5, "B": 3, "N": 3, "p": 1}
knight_scores = [[0.0, 0.1, 0.2, 0.2, 0.2, 0.2, 0.1, 0.0],
[0.1, 0.3, 0.5, 0.5, 0.5, 0.5, 0.3, 0.1],
[0.2, 0.5, 0.6, 0.65, 0.65, 0.6, 0.5, 0.2],
[0.2, 0.55, 0.65, 0.7, 0.7, 0.65, 0.55, 0.2],
[0.2, 0.5, 0.65, 0.7, 0.7, 0.65, 0.5, 0.2],
[0.2, 0.55, 0.6, 0.65, 0.65, 0.6, 0.55, 0.2],
[0.1, 0.3, 0.5, 0.55, 0.55, 0.5, 0.3, 0.1],
[0.0, 0.1, 0.2, 0.2, 0.2, 0.2, 0.1, 0.0]]
bishop_scores = [[0.0, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.0],
[0.2, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.2],
[0.2, 0.4, 0.5, 0.6, 0.6, 0.5, 0.4, 0.2],
[0.2, 0.5, 0.5, 0.6, 0.6, 0.5, 0.5, 0.2],
[0.2, 0.4, 0.6, 0.6, 0.6, 0.6, 0.4, 0.2],
[0.2, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.2],
[0.2, 0.5, 0.4, 0.4, 0.4, 0.4, 0.5, 0.2],
[0.0, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.0]]
rook_scores = [[0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25],
[0.5, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.5],
[0.0, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.0],
[0.0, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.0],
[0.0, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.0],
[0.0, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.0],
[0.0, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.0],
[0.25, 0.25, 0.25, 0.5, 0.5, 0.25, 0.25, 0.25]]
queen_scores = [[0.0, 0.2, 0.2, 0.3, 0.3, 0.2, 0.2, 0.0],
[0.2, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.2],
[0.2, 0.4, 0.5, 0.5, 0.5, 0.5, 0.4, 0.2],
[0.3, 0.4, 0.5, 0.5, 0.5, 0.5, 0.4, 0.3],
[0.4, 0.4, 0.5, 0.5, 0.5, 0.5, 0.4, 0.3],
[0.2, 0.5, 0.5, 0.5, 0.5, 0.5, 0.4, 0.2],
[0.2, 0.4, 0.5, 0.4, 0.4, 0.4, 0.4, 0.2],
[0.0, 0.2, 0.2, 0.3, 0.3, 0.2, 0.2, 0.0]]
pawn_scores = [[0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8],
[0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7],
[0.3, 0.3, 0.4, 0.5, 0.5, 0.4, 0.3, 0.3],
[0.25, 0.25, 0.3, 0.45, 0.45, 0.3, 0.25, 0.25],
[0.2, 0.2, 0.2, 0.4, 0.4, 0.2, 0.2, 0.2],
[0.25, 0.15, 0.1, 0.2, 0.2, 0.1, 0.15, 0.25],
[0.25, 0.3, 0.3, 0.0, 0.0, 0.3, 0.3, 0.25],
[0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2]]
piece_position_scores = {"wN": knight_scores,
"bN": knight_scores[::-1],
"wB": bishop_scores,
"bB": bishop_scores[::-1],
"wQ": queen_scores,
"bQ": queen_scores[::-1],
"wR": rook_scores,
"bR": rook_scores[::-1],
"wp": pawn_scores,
"bp": pawn_scores[::-1]}
CHECKMATE = 1000
STALEMATE = 0
DEPTH = 3
def findBestMove(game_state, valid_moves, return_queue):
global next_move
next_move = None
random.shuffle(valid_moves)
findMoveNegaMaxAlphaBeta(game_state, valid_moves, DEPTH, -CHECKMATE, CHECKMATE,
1 if game_state.white_to_move else -1)
return_queue.put(next_move)
def findMoveNegaMaxAlphaBeta(game_state, valid_moves, depth, alpha, beta, turn_multiplier):
global next_move
if depth == 0:
return turn_multiplier * scoreBoard(game_state)
# move ordering - implement later //TODO
max_score = -CHECKMATE
for move in valid_moves:
game_state.makeMove(move)
next_moves = game_state.getValidMoves()
score = -findMoveNegaMaxAlphaBeta(game_state, next_moves, depth - 1, -beta, -alpha, -turn_multiplier)
if score > max_score:
max_score = score
if depth == DEPTH:
next_move = move
game_state.undoMove()
if max_score > alpha:
alpha = max_score
if alpha >= beta:
break
return max_score
def scoreBoard(game_state):
"""
Score the board. A positive score is good for white, a negative score is good for black.
"""
if game_state.checkmate:
if game_state.white_to_move:
return -CHECKMATE # black wins
else:
return CHECKMATE # white wins
elif game_state.stalemate:
return STALEMATE
score = 0
for row in range(len(game_state.board)):
for col in range(len(game_state.board[row])):
piece = game_state.board[row][col]
if piece != "--":
piece_position_score = 0
if piece[1] != "K":
piece_position_score = piece_position_scores[piece][row][col]
if piece[0] == "w":
score += piece_score[piece[1]] + piece_position_score
if piece[0] == "b":
score -= piece_score[piece[1]] + piece_position_score
return score
def findRandomMove(valid_moves):
"""
Picks and returns a random valid move.
"""
return random.choice(valid_moves)