Skip to content

Commit 12aa210

Browse files
Merge pull request victorpreston#4 from atugharajohn/A.John
new chess game project added and remaining projects have been added to project list
2 parents d578d7e + 280c322 commit 12aa210

File tree

17 files changed

+404
-0
lines changed

17 files changed

+404
-0
lines changed

0x24-Chess_Game/ChessEngine.py

Lines changed: 222 additions & 0 deletions
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+

0x24-Chess_Game/ChessGame.py

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
import pygame as p
2+
import ChessEngine
3+
4+
WIDTH = HEIGHT = 512
5+
DIMENSIONS = 8
6+
SQ_SIZE = HEIGHT// DIMENSIONS
7+
MAX_FPS = 15
8+
IMAGES = {}
9+
10+
def loadImages():
11+
pieces = ['wp', 'wR', 'wN', 'wB', 'wQ', 'wK', 'bp', 'bR', 'bN', 'bB', 'bQ', 'bK' ]
12+
for piece in pieces:
13+
IMAGES[piece] = p.transform.scale(p.image.load("images/" + piece + ".png"), (SQ_SIZE, SQ_SIZE))
14+
15+
def main():
16+
p.init()
17+
screen = p.display.set_mode((WIDTH, HEIGHT))
18+
clock = p.time.Clock()
19+
screen.fill(p.Color("white"))
20+
gs = ChessEngine.GameState()
21+
validMoves = gs.getValidMoves()
22+
moveMade = False
23+
animate = False
24+
loadImages()
25+
running = True
26+
sqSelected = ()
27+
playerClicks = []
28+
gameOver = False
29+
while running:
30+
for e in p.event.get():
31+
if e.type == p.QUIT:
32+
running = False
33+
elif e.type == p.MOUSEBUTTONDOWN:
34+
if not gameOver:
35+
location = p.mouse.get_pos()
36+
col = location[0]//SQ_SIZE
37+
row = location[1]//SQ_SIZE
38+
if sqSelected == (row, col):
39+
sqSelected = ()
40+
playerClicks = []
41+
else:
42+
sqSelected = (row, col)
43+
playerClicks.append(sqSelected)
44+
if len(playerClicks) == 1 and (gs.board[row][col] == "--"):
45+
sqSelected = ()
46+
playerClicks = []
47+
if len(playerClicks) == 2:
48+
move = ChessEngine.Move(playerClicks[0], playerClicks[1], gs.board)
49+
for i in range(len(validMoves)):
50+
if move == validMoves[i]:
51+
gs.makeMove(move)
52+
moveMade = True
53+
animate = True
54+
sqSelected = ()
55+
playerClicks = []
56+
if not moveMade:
57+
playerClicks = [sqSelected]
58+
elif e.type == p.KEYDOWN:
59+
if e.key == p.K_z:
60+
gs.undoMove()
61+
moveMade = True
62+
animate = False
63+
if e.key == p.K_r:
64+
gs = ChessEngine.GameState()
65+
validMoves = gs.getValidMoves()
66+
sqSelected = ()
67+
playerClicks = []
68+
moveMade = False
69+
animate = False
70+
if moveMade:
71+
if animate:
72+
animatedMoves(gs.moveLog[-1], screen, gs.board,clock)
73+
validMoves = gs.getValidMoves()
74+
moveMade = False
75+
animate = False
76+
drawGameState(screen, gs, validMoves, sqSelected)
77+
if gs.checkMate:
78+
gameOver = True
79+
if gs.whiteToMove:
80+
drawText(screen, 'Black wins by checkmate')
81+
else:
82+
drawText(screen, 'White wins by checkmate')
83+
elif gs.staleMate:
84+
gameOver =True
85+
drawText(screen, 'Stalemate');
86+
clock.tick(MAX_FPS)
87+
p.display.flip()
88+
89+
def highlightSquares(screen, gs, validMoves, sqSelected):
90+
if sqSelected != ():
91+
r, c = sqSelected
92+
if gs.board[r][c][0] == ('w' if gs.whiteToMove else 'b'):
93+
s = p.Surface((SQ_SIZE, SQ_SIZE))
94+
s.set_alpha(100)
95+
s.fill(p.Color('blue'))
96+
screen.blit(s, (c*SQ_SIZE, r*SQ_SIZE))
97+
s.fill(p.Color("yellow"))
98+
for moves in validMoves:
99+
if moves.startRow == r and moves.startCol == c:
100+
screen.blit(s, (SQ_SIZE*moves.endCol, SQ_SIZE*moves.endRow))
101+
102+
def drawGameState(screen, gs, validMoves, sqSelected):
103+
drawBoard(screen)
104+
highlightSquares(screen, gs, validMoves, sqSelected)
105+
drawPieces(screen, gs.board)
106+
107+
def drawBoard(screen):
108+
global colors
109+
colors = [p.Color("white"), p.Color("grey")]
110+
for r in range(DIMENSIONS):
111+
for c in range(DIMENSIONS):
112+
color = colors[(r+c) % 2]
113+
p.draw.rect(screen, color, p.Rect(c*SQ_SIZE, r*SQ_SIZE, SQ_SIZE, SQ_SIZE))
114+
115+
def drawPieces(screen, board):
116+
for r in range(DIMENSIONS):
117+
for c in range(DIMENSIONS):
118+
piece = board[r][c]
119+
if piece != "--":
120+
screen.blit(IMAGES[piece], p.Rect(c*SQ_SIZE, r*SQ_SIZE, SQ_SIZE, SQ_SIZE))
121+
122+
def animatedMoves(move, screen,board, clock):
123+
global colors
124+
dR = move.endRow - move.startRow
125+
dC = move.endCol - move.startCol
126+
framesPerSquare = 5
127+
frameCount = (abs(dR) + abs(dC)) * framesPerSquare
128+
for frame in range(frameCount + 1):
129+
r,c =((move.startRow + dR*frame/frameCount, move.startCol + dC*frame/frameCount))
130+
drawBoard(screen)
131+
drawPieces(screen, board)
132+
color = colors[(move.endRow + move.endCol)%2]
133+
endSquare = p.Rect(move.endCol*SQ_SIZE, move.endRow*SQ_SIZE, SQ_SIZE, SQ_SIZE)
134+
p.draw.rect(screen, color, endSquare)
135+
if move.pieceCaptured != "--":
136+
screen.blit(IMAGES[move.pieceCaptured], endSquare)
137+
138+
screen.blit(IMAGES[move.pieceMoved], p.Rect(c*SQ_SIZE, r*SQ_SIZE, SQ_SIZE, SQ_SIZE))
139+
p.display.flip()
140+
clock.tick(60)
141+
142+
def drawText(screen, text):
143+
font = p.font.SysFont("Helvitca", 32, True, False)
144+
textObject = font.render(text, True, p.Color('Gray'))
145+
textLocation = p.Rect(0, 0, WIDTH, HEIGHT).move(WIDTH/2 - textObject.get_width()/2, HEIGHT/2 - textObject.get_height()/2)
146+
screen.blit(textObject, textLocation)
147+
textObject = font.render(text, True, p.Color("Black"))
148+
screen.blit(textObject, textLocation.move(2,2))
149+
150+
151+
if __name__ == "__main__":
152+
main()

0 commit comments

Comments
 (0)