-
Notifications
You must be signed in to change notification settings - Fork 0
/
ai.py
160 lines (135 loc) · 4.46 KB
/
ai.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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
import random
pieceScore = {"K": 0, "Q": 20, "R": 12, "B": 7, "N": 6, "P": 2}
CHECKMATE = 2000
DREW = 0
level = 3
# random move generator valid possible moves
def findRandomMove(validMoves):
return validMoves[random.randint(0, len(validMoves) - 1)]
# greedy algorithm for chess
def greedyAlgo(gs, validMoves):
turnMultiplier = 1 if gs.whiteToMove else -1
opponentMinMaxScore = CHECKMATE
# maxScore = -CHECKMATE
bestPlayerMove = None
random.shuffle(validMoves)
for playerMove in validMoves:
gs.makeMove(playerMove)
opponentMoves = gs.getValidMoves()
if gs.staleMate:
opponentMaxScore = DREW
elif gs.checkMate:
opponentMaxScore = -CHECKMATE
else:
opponentMaxScore = -CHECKMATE
for opponentMove in opponentMoves:
gs.makeMove(opponentMove)
if gs.checkMate:
score = -turnMultiplier * CHECKMATE
elif gs.staleMate:
score = DREW
else:
score = -turnMultiplier * scoreMaterial(gs.board)
if score > opponentMaxScore:
opponentMaxScore = score
# bestPlayerMove = playerMove
gs.undoMove()
if opponentMinMaxScore > opponentMaxScore:
opponentMinMaxScore = opponentMaxScore
bestPlayerMove = playerMove
gs.undoMove()
return bestPlayerMove
# helper method for first recursive
def findBestMove(gs, validMoves):
global nextMove
nextMove = None
# findMoveNegaMax(gs, validMoves, DEPTH, 1 if gs.whiteToMove else -1)
findMoveNegaMaxAlphaBeta(gs, validMoves, level, -CHECKMATE, CHECKMATE, 1 if gs.whiteToMove else -1)
return nextMove
# min max alog
def findMoveMinMax(gs, validMoves, depth, whiteToMove):
global nextMove
if depth == 0:
return scoreBoard(gs)
random.shuffle(validMoves)
if whiteToMove:
maxScore = -CHECKMATE
for move in validMoves:
gs.makeMove(move)
nextMoves = gs.getValidMoves()
score = findMoveMinMax(gs, nextMoves, depth - 1, False)
if score > maxScore:
maxScore = score
if depth == level:
nextMove = move
gs.undoMove()
return maxScore
else:
minScore = CHECKMATE
for move in validMoves:
gs.makeMove(move)
nextMoves = gs.getValidMoves()
score = findMoveMinMax(gs, nextMoves, depth - 1, True)
if score < minScore:
minScore = score
if depth == level:
nextMove = move
gs.undoMove()
return minScore
# Nega min max
def findMoveNegaMax(gs, validMoves, depth, turnMultiplier):
global nextMove
if depth == 0:
return turnMultiplier * scoreBoard(gs)
maxScore = -CHECKMATE
random.shuffle(validMoves)
for move in validMoves:
gs.makeMove(move)
nextMoves = gs.getValidMoves()
score = -findMoveNegaMax(gs, nextMoves, depth - 1, -turnMultiplier)
if score > maxScore:
maxScore = score
if level == depth:
nextMove = move
gs.undoMove()
return maxScore
# Nega min max with Alpha Beta
def findMoveNegaMaxAlphaBeta(gs, validMoves, depth,alpha, beta, turnMultiplier):
global nextMove
if depth == 0:
return turnMultiplier * scoreBoard(gs)
# move ordering - little more efficient
maxScore = -CHECKMATE
random.shuffle(validMoves)
for move in validMoves:
gs.makeMove(move)
nextMoves = gs.getValidMoves()
score = -findMoveNegaMaxAlphaBeta(gs, nextMoves, depth - 1,-beta, -alpha, -turnMultiplier)
if score > maxScore:
maxScore = score
if level == depth:
nextMove = move
gs.undoMove()
if maxScore > alpha:
alpha = maxScore
if alpha >= beta:
break
return maxScore
def scoreBoard(gs):
if gs.checkMate:
if gs.whiteToMove:
return -CHECKMATE
else:
return CHECKMATE
elif gs.staleMate:
return DREW
score = 0
for row in gs.board:
for square in row:
if square[0] == 'w':
score += pieceScore[square[1]]
elif square[0] == 'b':
score -= pieceScore[square[1]]
return score
def scoreMaterial(board):
pass