So I use Pycharm 2020 for my IDE. Pygame 1.9.6 to run it, the chess board. I use python 3.7.4.
I'm trying to create a working chess board in python. I've done the valid moves for white pawns. But the black pawns aren't working for some reason. All that's different really in the coding for them is changing up the row and what column a pawn can do.
Code:
class GameState:
def __init__(self):
self.board = [
["bR", "bN", "bB", "bQ", "bK", "bB", "bN", "bR"],
["bp", "bp", "bp", "bp", "bp", "bp", "bp", "bp"],
["--", "--", "--", "--", "wp", "--", "--", "--"],
["--", "--", "--", "--", "--", "--", "--", "--"],
["--", "--", "--", "--", "--", "--", "--", "--"],
["--", "--", "--", "--", "--", "bp", "--", "--"],
["wp", "wp", "wp", "wp", "wp", "wp", "wp", "wp"],
["wR", "wN", "wB", "wQ", "wK", "wB", "wN", "wR"]]
self.moveFunctions = {'p': self.getPawnMoves, 'R': self.getRookMoves, 'N': self.getKnightMoves,
'B': self.getBishopMoves, 'Q': self.getQueenMoves, 'K': self.getKingMoves}
self.whiteToMove = True
self.moveLog = []
'''
Takes a Move as a parameter and executes it (this will not work for castling, pawn promotion, and en passant
'''
def makeMove(self, move):
self.board[move.startRow][move.startCol] = "--"
self.board[move.endRow][move.endCol] = move.pieceMoved
self.moveLog.append(move)
self.whiteToMove = not self.whiteToMove
'''
Undo the last move
'''
def undoMove(self):
if len(self.moveLog) != 0:
move = self.moveLog.pop()
self.board[move.startRow][move.startCol] = move.pieceMoved
self.board[move.endRow][move.endCol] = move.pieceCaptured
self.whiteToMove = not self.whiteToMove
'''
All moves considering checks
'''
def getValidMoves(self):
return self.getAllPossibleMoves()
'''
All moves without considering checks
'''
def getAllPossibleMoves(self):
moves = []
for r in range(len(self.board)):
for c in range(len(self.board[r])):
turn = self.board[r][c][0]
if (turn == 'w' and self.whiteToMove) or (turn == 'b' and not self.whiteToMove):
piece = self.board[r][c][1]
self.moveFunctions[piece](r, c, moves)
return moves
'''
Get all the pawn moves for the pawn located at row, col and add these moves to the list
'''
def getPawnMoves(self, r, c, moves):
if self.whiteToMove:
if self.board[r-1][c] == "--":
moves.append(Move((r, c), (r-1, c), self.board))
if r == 6 and self.board[r-2][c] == "--":
moves.append(Move((r, c), (r-2, c), self.board))
if c-1 >= 0:
if self.board[r-1][c-1][0] == 'b':
moves.append(Move((r, c), (r-1, c-1), self.board))
if c+1 <= 7:
if self.board[r-1][c+1][0] == 'b':
moves.append(Move((r, c), (r-1, c+1), self.board))
else:
if self.board[r+1][c] == "--":
moves.append(Move((r, c), (r+1, c), self.board))
if r == 1 and self.board[r+2][c] == "--":
moves.append(Move((r, c), (r+2, c), self.board))
if c-1 >= 0:
if self.board[r+1][c-1][0] == 'w':
moves.append(Move((r, c), (r+1, c-1), self.board))
if c+1 <= 7:
if self.board[r+1][c+1][0] == 'w':
moves.append(Move((r, c), (r+1, c+1), self.board))
'''
Get all the rook moves for the rook located at row, col and add these moves to the list
'''
def getRookMoves(self, r, c, moves):
pass
'''
Get all the knight moves for the knight located at row, col and add these moves to the list
'''
def getKnightMoves(self, r, c, moves):
pass
'''
Get all the bishop moves for the bishop located at row, col and add these moves to the list
'''
def getBishopMoves(self, r, c, moves):
pass
'''
Get all the queen moves for the queen located at row, col and add these moves to the list
'''
def getQueenMoves(self, r, c, moves):
pass
'''
Get all the king moves for the king located at row, col and add these moves to the list
'''
def getKingMoves(self, r, c, moves):
pass
class Move():
ranksToRows = {"1": 7, "2": 6, "3": 5, "4": 4,
"5": 3, "6": 2, "7": 1, "8": 0}
rowsToRanks = {v: k for k, v in ranksToRows.items()}
filesToCols = {"a": 0, "b": 1, "c": 2, "d": 3,
"e": 4, "f": 5, "g": 6, "h": 7}
colsToFiles = {v: k for k, v in filesToCols.items()}
def __init__(self, startSq, endSq, board):
self.startRow = startSq[0]
self.startCol = startSq[1]
self.endRow = endSq[0]
self.endCol = endSq[1]
self.pieceMoved = board[self.startRow][self.startCol]
self.pieceCaptured = board[self.endRow][self.endCol]
self.moveID = self.startRow * 1000 + self.startCol * 100 + self.endRow * 10 + self.endCol
'''
Overriding the equals method
'''
def __eq__(self, other):
if isinstance(other, Move):
return self.moveID == other.moveID
return False
def getChessNotation(self):
return self.getRankFile(self.startRow, self.startCol) + self.getRankFile(self.endRow, self.endCol)
def getRankFile(self, r, c):
return self.colsToFiles[c] + self.rowsToRanks[r]
import pygame as p
from Chess import ChessEngine
WIDTH = HEIGHT = 512
DIMENSION = 8
SQ_SIZE = HEIGHT // DIMENSION
MAX_FPS = 15
IMAGES = {}
'''
Initialize a global dictionary of images. This will be called exactly once in the main
'''
def loadImages():
pieces = ['wp', 'wR', 'wN', 'wB', 'wK', 'wQ', 'bp', 'bR', 'bN', 'bB', 'bK', 'bQ']
for piece in pieces:
IMAGES[piece] = p.transform.scale(p.image.load("images/" + piece + ".png"), (SQ_SIZE, SQ_SIZE))
'''
The main driver for our code. This will handle user input and updating the graphics.
'''
def main():
p.init()
screen = p.display.set_mode((WIDTH, HEIGHT))
clock = p.time.Clock()
screen.fill(p.Color("white"))
gs = ChessEngine.GameState()
validMoves = gs.getValidMoves()
moveMade = False
loadImages()
running = True
sqSelected = ()
playerClicks = []
while running:
for e in p.event.get():
if e.type == p.QUIT:
running = False
elif e.type == p.MOUSEBUTTONDOWN:
location = p.mouse.get_pos()
col = location[0]//SQ_SIZE
row = location[1]//SQ_SIZE
if sqSelected == (row, col):
sqSelected = ()
playerClicks = []
else:
sqSelected = (row, col)
playerClicks.append(sqSelected)
if len(playerClicks) == 2:
move = ChessEngine.Move(playerClicks[0], playerClicks[1], gs.board)
print(move.getChessNotation())
if move in validMoves:
gs.makeMove(move)
makeMove = True
sqSelected = ()
playerClicks = []
elif e.type == p.KEYDOWN:
if e.key == p.K_u:
gs.undoMove()
moveMade = True
if moveMade:
validMoves = gs.getValidMoves()
moveMade = False
drawGameState(screen, gs)
clock.tick(MAX_FPS)
p.display.flip()
'''
Responsible for all the graphics within a current game state.
'''
def drawGameState(screen, gs):
drawBoard(screen)
drawPieces(screen, gs.board)
'''
Draw the squares on the board. The top left square is always light.
'''
def drawBoard(screen):
colors = [p.Color("white"), p.Color("grey")]
for r in range(DIMENSION):
for c in range(DIMENSION):
color = colors[((r+c) % 2)]
p.draw.rect(screen, color, p.Rect(c * SQ_SIZE, r * SQ_SIZE, SQ_SIZE, SQ_SIZE))
'''
Draw the pieces on the board using the current GameState.board
'''
def drawPieces(screen, board):
for r in range(DIMENSION):
for c in range(DIMENSION):
piece = board[r][c]
if piece != "--":
screen.blit(IMAGES[piece], p.Rect(c * SQ_SIZE, r * SQ_SIZE, SQ_SIZE, SQ_SIZE))
if __name__ == "__main__":
main()
What I have tried:
I've tried debugging it says it fine. I've tried changing the code for the black pawn, but nothing.