-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathChessRules.py
executable file
·229 lines (202 loc) · 7.56 KB
/
ChessRules.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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
#! /usr/bin/env python
class ChessRules:
def IsCheckmate(self,board,color):
#returns true if 'color' player is in checkmate
#Call GetListOfValidMoves for each piece of current player
#If there aren't any valid moves for any pieces, then return true
if color == "black":
myColor = 'b'
enemyColor = 'w'
else:
myColor = 'w'
enemyColor = 'b'
myColorValidMoves = [];
for row in range(8):
for col in range(8):
piece = board[row][col]
if myColor in piece:
myColorValidMoves.extend(self.GetListOfValidMoves(board,color,(row,col)))
if len(myColorValidMoves) == 0:
return True
else:
return False
def GetListOfValidMoves(self,board,color,fromTuple):
legalDestinationSpaces = []
for row in range(8):
for col in range(8):
d = (row,col)
if self.IsLegalMove(board,color,fromTuple,d):
if not self.DoesMovePutPlayerInCheck(board,color,fromTuple,d):
legalDestinationSpaces.append(d)
return legalDestinationSpaces
def IsLegalMove(self,board,color,fromTuple,toTuple):
#print "IsLegalMove with fromTuple:",fromTuple,"and toTuple:",toTuple,"color = ",color
fromSquare_r = fromTuple[0]
fromSquare_c = fromTuple[1]
toSquare_r = toTuple[0]
toSquare_c = toTuple[1]
fromPiece = board[fromSquare_r][fromSquare_c]
toPiece = board[toSquare_r][toSquare_c]
if color == "black":
enemyColor = 'w'
if color == "white":
enemyColor = 'b'
if fromTuple == toTuple:
return False
if "P" in fromPiece:
#Pawn
if color == "black":
if toSquare_r == fromSquare_r+1 and toSquare_c == fromSquare_c and toPiece == 'e':
#moving forward one space
return True
if fromSquare_r == 1 and toSquare_r == fromSquare_r+2 and toSquare_c == fromSquare_c and toPiece == 'e':
#black pawn on starting row can move forward 2 spaces if there is no one directly ahead
if self.IsClearPath(board,fromTuple,toTuple):
return True
if toSquare_r == fromSquare_r+1 and (toSquare_c == fromSquare_c+1 or toSquare_c == fromSquare_c-1) and enemyColor in toPiece:
#attacking
return True
elif color == "white":
if toSquare_r == fromSquare_r-1 and toSquare_c == fromSquare_c and toPiece == 'e':
#moving forward one space
return True
if fromSquare_r == 6 and toSquare_r == fromSquare_r-2 and toSquare_c == fromSquare_c and toPiece == 'e':
#black pawn on starting row can move forward 2 spaces if there is no one directly ahead
if self.IsClearPath(board,fromTuple,toTuple):
return True
if toSquare_r == fromSquare_r-1 and (toSquare_c == fromSquare_c+1 or toSquare_c == fromSquare_c-1) and enemyColor in toPiece:
#attacking
return True
elif "R" in fromPiece:
#Rook
if (toSquare_r == fromSquare_r or toSquare_c == fromSquare_c) and (toPiece == 'e' or enemyColor in toPiece):
if self.IsClearPath(board,fromTuple,toTuple):
return True
elif "T" in fromPiece:
#Knight
col_diff = toSquare_c - fromSquare_c
row_diff = toSquare_r - fromSquare_r
if toPiece == 'e' or enemyColor in toPiece:
if col_diff == 1 and row_diff == -2:
return True
if col_diff == 2 and row_diff == -1:
return True
if col_diff == 2 and row_diff == 1:
return True
if col_diff == 1 and row_diff == 2:
return True
if col_diff == -1 and row_diff == 2:
return True
if col_diff == -2 and row_diff == 1:
return True
if col_diff == -2 and row_diff == -1:
return True
if col_diff == -1 and row_diff == -2:
return True
elif "B" in fromPiece:
#Bishop
if ( abs(toSquare_r - fromSquare_r) == abs(toSquare_c - fromSquare_c) ) and (toPiece == 'e' or enemyColor in toPiece):
if self.IsClearPath(board,fromTuple,toTuple):
return True
elif "Q" in fromPiece:
#Queen
if (toSquare_r == fromSquare_r or toSquare_c == fromSquare_c) and (toPiece == 'e' or enemyColor in toPiece):
if self.IsClearPath(board,fromTuple,toTuple):
return True
if ( abs(toSquare_r - fromSquare_r) == abs(toSquare_c - fromSquare_c) ) and (toPiece == 'e' or enemyColor in toPiece):
if self.IsClearPath(board,fromTuple,toTuple):
return True
elif "K" in fromPiece:
#King
col_diff = toSquare_c - fromSquare_c
row_diff = toSquare_r - fromSquare_r
if toPiece == 'e' or enemyColor in toPiece:
if abs(col_diff) == 1 and abs(row_diff) == 0:
return True
if abs(col_diff) == 0 and abs(row_diff) == 1:
return True
if abs(col_diff) == 1 and abs(row_diff) == 1:
return True
return False #if none of the other "True"s are hit above
def DoesMovePutPlayerInCheck(self,board,color,fromTuple,toTuple):
#makes a hypothetical move; returns True if it puts current player into check
fromSquare_r = fromTuple[0]
fromSquare_c = fromTuple[1]
toSquare_r = toTuple[0]
toSquare_c = toTuple[1]
fromPiece = board[fromSquare_r][fromSquare_c]
toPiece = board[toSquare_r][toSquare_c]
#make the move, then test if 'color' is in check
board[toSquare_r][toSquare_c] = fromPiece
board[fromSquare_r][fromSquare_c] = 'e'
retval = self.IsInCheck(board,color)
#undo temporary move
board[toSquare_r][toSquare_c] = toPiece
board[fromSquare_r][fromSquare_c] = fromPiece
return retval
def IsInCheck(self,board,color):
#check if 'color' is in check
#scan through squares for all enemy pieces; if there IsLegalMove to color's king, then return True.
if color == "black":
myColor = 'b'
enemyColor = 'w'
enemyColorFull = 'white'
else:
myColor = 'w'
enemyColor = 'b'
enemyColorFull = 'black'
kingTuple = (0,0)
#First, get current player's king location
for row in range(8):
for col in range(8):
piece = board[row][col]
if 'K' in piece and myColor in piece:
kingTuple = (row,col)
#Check if any of enemy player's pieces has a legal move to current player's king
for row in range(8):
for col in range(8):
piece = board[row][col]
if enemyColor in piece:
if self.IsLegalMove(board,enemyColorFull,(row,col),kingTuple):
return True
return False
def IsClearPath(self,board,fromTuple,toTuple):
#Return true if there is nothing in a straight line between fromTuple and toTuple, non-inclusive
#Direction could be +/- vertical, +/- horizontal, +/- diagonal
fromSquare_r = fromTuple[0]
fromSquare_c = fromTuple[1]
toSquare_r = toTuple[0]
toSquare_c = toTuple[1]
fromPiece = board[fromSquare_r][fromSquare_c]
if abs(fromSquare_r - toSquare_r) <= 1 and abs(fromSquare_c - toSquare_c) <= 1:
#The base case: just one square apart
return True
else:
if toSquare_r > fromSquare_r and toSquare_c == fromSquare_c:
#vertical +
newTuple = (fromSquare_r+1,fromSquare_c)
elif toSquare_r < fromSquare_r and toSquare_c == fromSquare_c:
#vertical -
newTuple = (fromSquare_r-1,fromSquare_c)
elif toSquare_r == fromSquare_r and toSquare_c > fromSquare_c:
#horizontal +
newTuple = (fromSquare_r,fromSquare_c+1)
elif toSquare_r == fromSquare_r and toSquare_c < fromSquare_c:
#horizontal -
newTuple = (fromSquare_r,fromSquare_c-1)
elif toSquare_r > fromSquare_r and toSquare_c > fromSquare_c:
#diagonal "SE"
newTuple = (fromSquare_r+1,fromSquare_c+1)
elif toSquare_r > fromSquare_r and toSquare_c < fromSquare_c:
#diagonal "SW"
newTuple = (fromSquare_r+1,fromSquare_c-1)
elif toSquare_r < fromSquare_r and toSquare_c > fromSquare_c:
#diagonal "NE"
newTuple = (fromSquare_r-1,fromSquare_c+1)
elif toSquare_r < fromSquare_r and toSquare_c < fromSquare_c:
#diagonal "NW"
newTuple = (fromSquare_r-1,fromSquare_c-1)
if board[newTuple[0]][newTuple[1]] != 'e':
return False
else:
return self.IsClearPath(board,newTuple,toTuple)