I use Pycharm 2020 community as an IDE. I use pygame 1.9.6 to the play chess board. I use Python 3.7.4.
When ever I'm trying to make a valid pawn move after whites pawn move nothing happens. I even do the trick where you put a print("here") to see if a code is reaching, but it's not. Put say if I make 3+ pawns moves then I hit undo all by pressing 'u' 3 times then it says "here" after that, but when I go to make a black pawn move nothing happens or a white pawn move first then black nothing still. I don't know why my code isn't reaching it.
Code:
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
'''
class GameState:
def __init__(self):
self.board = [
["bR", "bN", "bB", "bQ", "bK", "bB", "bN", "bR"],
["bp", "bp", "bp", "bp", "bp", "bp", "bp", "bp"],
["--", "--", "--", "--", "--", "--", "--", "--"],
["--", "--", "--", "--", "--", "--", "--", "--"],
["--", "--", "--", "--", "--", "--", "--", "--"],
["--", "--", "--", "--", "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] == "--":
print("here1")
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):
directions = ((-1, 0), (0, -1), (1, 0), (0, 1))
enemyColor = "b" if self.whiteToMove else "w"
for d in directions:
for i in range(1, 0):
endRow = r + d[0] * i
endCol = c + d[1] * i
if 0 <= endRow < 8 and 0 <= endCol < 8:
endPiece = self.board[endRow][endCol]
if endPiece == "--":
moves.append(Move((r, c), (endRow, endCol), self.board))
elif endPiece[0] == enemyColor:
moves.append(Move((r, c), (endRow, endCol), self.board))
break
else:
break
else:
break
'''
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):
knightMoves = ((-2, -1), (-2, 1), (-1, -2), (-1, 2), (1, -2), (1, 2), (2, -1), (2, 1))
allyColor = 'w' if self.whiteToMove else "b"
for m in knightMoves:
endRow = r + m[0]
endCol = c + m[0]
if 0 <= endRow < 8 and 0 <= endCol < 8:
endPiece = self.board[endRow][endCol]
if endPiece[0] != allyColor:
moves.append(Move((r, c), (endRow, endCol), self.board))
'''
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):
directions = ((-1, -1), (-1, 1), (1, -1), (1, 1))
enemyColor = "b" if self.whiteToMove else "w"
for d in directions:
for i in range(1, 8):
endRow = r + d[0] * i
endCol = c + d[1] * i
if 0 <= endRow < 8 and 0 <= endCol < 8:
endPiece = self.board[endRow][endCol]
if endPiece == "--":
moves.append(Move((r, c), (endRow, endCol), self.board))
elif endPiece[0] == enemyColor:
moves.append(Move((r, c), (endRow, endCol), self.board))
break
else:
break
else:
break
'''
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):
self.getRookMoves(r, c, moves)
self.getBishopMoves(r, c, moves)
'''
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):
kingMoves = ((-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1))
allyColor = "w" if self.whiteToMove else "b"
for i in range(8):
endRow = r + kingMoves[i][0]
endCol = c + kingMoves[i][1]
if 0 <= endRow < 8 and 0 <= endCol <8:
endPiece = self.board[endRow][endCol]
if endPiece[0] != allyColor:
moves.append(Move((r, c), (endRow, endCol), self.board))
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]
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 = []
else:
playerClicks = [sqSelected]
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 to change the else statement in black pawn moves to elif not self.whiteToMove:
but nothing. I've finding where the code reaches, it reaches in all the places like getValidMoves, undoMove, getAllPossibleMoves. I've tried checking if any my code is wrong, but I can't find what. I just don't know why it's working. I've tried everything I could think of honestly. I just need help, maybe with blind spots.