Skip to content

Commit 3ef07c8

Browse files
committed
chess engine added
1 parent 8c84723 commit 3ef07c8

File tree

1 file changed

+222
-0
lines changed

1 file changed

+222
-0
lines changed

0x24-Chess_Game/ChessEngine.py

+222
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
2+
class GameState:
3+
4+
def __init__(self):
5+
self.board = [
6+
["bR", "bN", "bB", "bQ", "bK", "bB", "bN", "bR"],
7+
["bp", "bp", "bp", "bp", "bp", "bp", "bp", "bp"],
8+
["--", "--", "--", "--", "--", "--", "--", "--"],
9+
["--", "--", "--", "--", "--", "--", "--", "--"],
10+
["--", "--", "--", "--", "--", "--", "--", "--"],
11+
["--", "--", "--", "--", "--", "--", "--", "--"],
12+
["wp", "wp", "wp", "wp", "wp", "wp", "wp", "wp"],
13+
["wR", "wN", "wB", "wQ", "wK", "wB", "wN", "wR"]]
14+
self.moveFunctions = {'p': self.getPawnMoves, 'R': self.getRookMoves, 'N': self.getKnightMoves,
15+
'B': self.getBishopMoves, 'Q': self.getQueenMoves, 'K': self.getKingMoves}
16+
self.whiteToMove = True,
17+
self.moveLog = []
18+
self.whiteKingLocation = (7, 4)
19+
self.blackKingLocation = (0, 4)
20+
self.checkMate = False
21+
self.staleMate = False
22+
23+
def makeMove(self, move):
24+
self.board[move.startRow][move.startCol] = "--"
25+
self.board[move.endRow][move.endCol] = move.pieceMoved
26+
self.moveLog.append(move)
27+
self.whiteToMove = not self.whiteToMove
28+
if move.pieceMoved == "wK":
29+
self.whiteKingLocation = (move.endRow, move.endCol)
30+
elif move.pieceMoved == "bK":
31+
self.blackKingLocation = (move.endRow, move.endCol)
32+
33+
if move.isPawnPromotion:
34+
self.board[move.endRow][move.endCol] = move.pieceMoved[0] + "Q"
35+
36+
37+
def undoMove(self):
38+
if len(self.moveLog) != 0:
39+
move = self.moveLog.pop()
40+
self.board[move.startRow][move.startCol] = move.pieceMoved
41+
self.board[move.endRow][move.endCol] = move.pieceCaptured
42+
self.whiteToMove = not self.whiteToMove
43+
if move.pieceMoved == "wK":
44+
self.whiteKingLocation = (move.startRow, move.startCol)
45+
if move.pieceMoved == "bK":
46+
self.blackKingLocation = (move.startRow, move.startCol)
47+
"""
48+
All move considering checks
49+
"""
50+
def getValidMoves(self):
51+
moves = self.getAllPossibleMoves()
52+
for i in range(len(moves)-1, -1, -1):
53+
self.makeMove(moves[i])
54+
self.whiteToMove = not self.whiteToMove
55+
if self.inCheck():
56+
moves.remove(moves[i])
57+
self.whiteToMove = not self.whiteToMove
58+
self.undoMove()
59+
if len(moves) == 0:
60+
if self.inCheck():
61+
self.checkMate = True
62+
else:
63+
self.staleMate = True
64+
else:
65+
self.checkMate = False
66+
self.staleMate = False
67+
68+
return moves
69+
70+
def inCheck(self):
71+
if self.whiteToMove:
72+
return self.squareUnderAttack(self.whiteKingLocation[0], self.whiteKingLocation[1])
73+
else:
74+
return self.squareUnderAttack(self.blackKingLocation[0], self.blackKingLocation[1])
75+
76+
def squareUnderAttack(self, r, c):
77+
self.whiteToMove = not self.whiteToMove
78+
oppMoves = self.getAllPossibleMoves()
79+
self.whiteToMove = not self.whiteToMove
80+
for move in oppMoves:
81+
if move.endRow == r and move.endCol == c:
82+
return True
83+
return False
84+
85+
86+
87+
88+
"""
89+
All move without considering checks
90+
"""
91+
def getAllPossibleMoves(self):
92+
moves = []
93+
for r in range(len(self.board)):
94+
for c in range(len(self.board[r])):
95+
turn = self.board[r][c][0] # b or w based on turn
96+
if(turn == 'w' and self.whiteToMove) or (turn == 'b' and not self.whiteToMove):
97+
piece = self.board[r][c][1]
98+
self.moveFunctions[piece](r,c, moves)
99+
return moves
100+
101+
102+
def getPawnMoves(self, r, c, moves):
103+
if self.whiteToMove:
104+
if self.board[r-1][c] == "--":
105+
moves.append(Move((r, c),(r-1, c), self.board))
106+
if r == 6 and self.board[r-2][c] == "--":
107+
moves.append(Move((r, c),(r-2, c), self.board))
108+
if c-1 >= 0:
109+
if self.board[r-1][c-1][0] == 'b':
110+
moves.append(Move((r, c),(r-1, c-1), self.board))
111+
if c+1 <= 7:
112+
if self.board[r-1][c+1][0] == 'b':
113+
moves.append(Move((r, c),(r-1, c+1), self.board))
114+
115+
else:
116+
if self.board[r+1][c] == "--":
117+
moves.append(Move((r, c),(r+1, c), self.board))
118+
if r == 1 and self.board[r+2][c] == "--":
119+
moves.append(Move((r, c),(r+2, c), self.board))
120+
if c-1 >= 0:
121+
if self.board[r+1][c-1][0] == 'w':
122+
moves.append(Move((r, c),(r+1, c-1), self.board))
123+
if c+1 <= 7:
124+
if self.board[r+1][c+1][0] == 'w':
125+
moves.append(Move((r, c),(r+1, c+1), self.board))
126+
127+
def getRookMoves(self, r, c, moves):
128+
directions = ((-1, 0), (0, -1), (1, 0), (0, 1))
129+
enemyColor = "b" if self.whiteToMove else "w"
130+
for d in directions:
131+
for i in range(1, 8):
132+
endRow = r + d[0] * i
133+
endCol = c + d[1] * i
134+
if 0 <= endRow < 8 and 0 <= endCol < 8:
135+
endPiece = self.board[endRow][endCol]
136+
if endPiece == "--":
137+
moves.append(Move((r,c), (endRow, endCol), self.board))
138+
elif endPiece[0] == enemyColor:
139+
moves.append(Move((r,c), (endRow, endCol), self.board))
140+
break
141+
else:
142+
break
143+
else:
144+
break
145+
146+
def getKnightMoves(self, r,c,moves):
147+
knightMoves = ((-2, -1), (-2, 1), (-1, -2), (-1, 2), (1, -2), (1, 2), (2, -1), (2,1))
148+
allyColor = "w" if self.whiteToMove else "b"
149+
for m in knightMoves:
150+
endRow = r + m[0]
151+
endCol = c + m[1]
152+
if 0 <= endRow < 8 and 0 <= endCol < 8:
153+
endPiece = self.board[endRow][endCol]
154+
if endPiece[0] != allyColor:
155+
moves.append(Move((r,c), (endRow, endCol), self.board))
156+
157+
def getBishopMoves(self, r,c,moves):
158+
directions = ((-1, -1), (-1, 1), (1, -1), (1, 1))
159+
enemyColor = "b" if self.whiteToMove else "w"
160+
for d in directions:
161+
for i in range(1, 8):
162+
endRow = r + d[0] * i
163+
endCol = c + d[1] * i
164+
if 0 <= endRow < 8 and 0 <= endCol < 8:
165+
endPiece = self.board[endRow][endCol]
166+
if endPiece == "--":
167+
moves.append(Move((r,c), (endRow, endCol), self.board))
168+
elif endPiece[0] == enemyColor:
169+
moves.append(Move((r,c), (endRow, endCol), self.board))
170+
break
171+
else:
172+
break
173+
else:
174+
break
175+
176+
def getQueenMoves(self, r,c,moves):
177+
self.getRookMoves(r, c, moves)
178+
self.getBishopMoves(r, c, moves)
179+
180+
def getKingMoves(self, r,c,moves):
181+
kingMoves = ((-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1,1) )
182+
allyColor = "w" if self.whiteToMove else "b"
183+
for i in range(8):
184+
endRow = r + kingMoves[i][0]
185+
endCol = c + kingMoves[i][1]
186+
if 0 <= endRow < 8 and 0 <= endCol < 8:
187+
endPiece = self.board[endRow][endCol]
188+
if endPiece[0] != allyColor:
189+
moves.append(Move((r,c), (endRow, endCol), self.board))
190+
class Move():
191+
192+
ranksToRow = {"1": 7, "2": 6, "3": 5, "4": 4,
193+
"5": 3, "6": 2, "7": 1, "8": 0}
194+
rowsToRanks = {v: k for k, v in ranksToRow.items()}
195+
filesToCols = {"a": 0, "b": 1, "c": 2, "d": 3,
196+
"e": 4, "f": 5, "g": 6, "h": 7}
197+
colsToFiles = {v: k for k, v in filesToCols.items()}
198+
199+
def __init__(self, startSq, endSq, board):
200+
self.startRow = startSq[0]
201+
self.startCol = startSq[1]
202+
self.endRow = endSq[0]
203+
self.endCol = endSq[1]
204+
self.pieceMoved = board[self.startRow][self.startCol]
205+
self.pieceCaptured = board[self.endRow][self.endCol]
206+
self.isPawnPromotion = False
207+
if (self.pieceMoved == 'wp' and self.endRow == 0) or (self.pieceMoved == 'bp' and self.endRow == 7):
208+
self.isPawnPromotion = True
209+
self.moveID = self.startRow * 1000 + self.startCol * 100 + self.endRow * 10 + self.endCol
210+
211+
def __eq__(self, other):
212+
if isinstance(other, Move):
213+
return self.moveID == other.moveID
214+
return False
215+
216+
217+
def getChessNotation(self):
218+
return self.getRankFile(self.startRow, self.startCol) + self.getRankFile(self.endRow, self.endCol)
219+
220+
def getRankFile(self, r, c):
221+
return self.colsToFiles[c] + self.rowsToRanks[r]
222+

0 commit comments

Comments
 (0)