Пример #1
0
class ChessRunner:

    def __init__(self):
        self.gui = ChessGUI()
        self.createPieces()
        self.checkmate = False

            
    
    def main(self):

        #Draw pieces on board
        for piece in self.whitePieces+self.blackPieces:
            #drawPiece() instead of draw() so piece.hasMoved isn't set to true
            piece.drawPiece(self.gui)
        
        self.currentTeam = self.whitePieces

        whiteInCheck = False
        blackInCheck = False

        #Loop will only exit when quit button is clicked
        while True:
            if self.checkmate:
                self.reset()
            else:
                if self.currentTeam == self.whitePieces:
                    #Check variable is solely for message purposes
                    if not whiteInCheck:
                       self.gui.printMessage("White's turn")
                    self.otherTeam = self.blackPieces
                else:
                    if not blackInCheck:
                        self.gui.printMessage("Black's turn")
                    self.otherTeam = self.whitePieces
                hasMoved = False

                #While no move has been made
                while not hasMoved:
                    #Get clicked square
                    square = self.gui.getInput()

                    #Check if there is a current team piece on the clicked square
                    if self.pieceOnSquare(self.currentTeam,square):
                        piece = self.pieceOnSquare(self.currentTeam,square)

                        #Highlight moves the piece can make without putting its king in check
                        for move in self.movesCanMakeWithCheck(piece):
                            self.gui.highlightSelectedSquare(move)
                        square = self.gui.getInput()

                        #If clicked square in  moves the piece can make without putting its king in check
                        if square in self.movesCanMakeWithCheck(piece):

                            #For printing move message
                            piecesInvolvedInMove = [piece]

                            #Castle logic
                            isCastleMove = False
                            if piece.getType() == 'King':
                                if square in piece.castleMoves(self.currentTeam,self.otherTeam):
                                    isCastleMove = True
                                   
                                    if square[0] < piece.getX():
                                         #If castling queenside
                                        leftRook = piece.getRookLeft(self.currentTeam)
                                        leftRook.setCoordinates((3,leftRook.getY()))
                                        leftRook.draw(self.gui)
                                        piecesInvolvedInMove.append(leftRook)
                                    else:
                                        #If castling kingside
                                        rightRook = piece.getRookRight(self.currentTeam)
                                        rightRook.setCoordinates((5,rightRook.getY()))
                                        rightRook.draw(self.gui)
                                        piecesInvolvedInMove.append(rightRook)

                            #Move piece
                            piece.setCoordinates(square)
                            hasMoved = True
                            piece.draw(self.gui)

                            self.gui.unHighlightAllSquares()
                            pieceToRemove = False

                            #Check if piece was taken
                            for otherPiece in self.otherTeam:
                                if piece.getCoordinates() == otherPiece.getCoordinates():
                                    pieceToRemove = otherPiece
                                    
                            #Removing piece logic
                            if pieceToRemove:
                                self.otherTeam.remove(pieceToRemove)
                                pieceToRemove.kill()
                                piecesInvolvedInMove.append(pieceToRemove)

                            #Print appropriate message to GUI
                            self.printMoveMessage(piecesInvolvedInMove,isCastleMove)
                            #Check if pawn is at the end of the board
                            self.checkForPawnToQueen(piece)
                        else:
                            #User clicked on a square that was an invalid move
                            self.gui.printMoves("Not a valid move")
                            self.gui.unHighlightAllSquares()
                    else:
                        #User didn't click on a current team piece
                        self.gui.printMoves("You must pick a "+self.getTeamString().lower()+" piece")
                        self.gui.unHighlightAllSquares()

                    #Check logic
                    king = self.otherTeam[0]
                    if king.isInCheck(self.otherTeam,self.currentTeam):
                        teamString = self.getOtherTeamString()
                        
                        #Checkmate logic
                        if self.otherTeamIsInCheckmate():
                            self.gui.printMessage("Checkmate! {0} loses".format(teamString))
                            self.checkmate = True
                        else:
                            if teamString == 'White':
                                #For message printing purposes
                                whiteInCheck = True
                            else:
                                blackInCheck = True
                            self.gui.printMessage(teamString+' king is in check.')
                    else:
                        whiteInCheck = False
                        blackInCheck = False
                if self.currentTeam == self.whitePieces:
                    self.currentTeam = self.blackPieces
                else:
                    self.currentTeam = self.whitePieces

    def checkForPawnToQueen(self,piece):
        
        if self.currentTeam == self.whitePieces:
            #For a white pawn
            if piece.getY() == 0 and piece.getType() == 'Pawn':
                #Create queen at pawn's coordinates
                queen = Queen('white')
                queen.setCoordinates(piece.getCoordinates())
                queen.draw(self.gui)
                self.currentTeam.append(queen)
                #Undraw pawn and remove it from current team
                piece.kill()
                self.currentTeam.remove(piece)
        else:
            if piece.getY() == 7 and piece.getType() == 'Pawn':
                #Same logic as above but for black
                queen = Queen('black')
                queen.setCoordinates(piece.getCoordinates())
                queen.draw(self.gui)
                self.currentTeam.append(queen)
                piece.kill()
                self.currentTeam.remove(piece)
    

    def otherTeamIsInCheckmate(self):
        king = self.otherTeam[0]
        totalMoves = []
        #Checking if there are any moves the other team can make that won't put them in check
        #If not, it is checkmate
        for piece in self.otherTeam:
            for move in piece.movesCanMake(self.otherTeam,self.currentTeam):
                previousCoordinates = piece.getCoordinates()
                piece.setCoordinates(move)
                pieceToRemove = False
                #Simulating if move would take piece
                for currentTeamPiece in self.currentTeam:
                    if piece.getCoordinates() == currentTeamPiece.getCoordinates():
                        pieceToRemove = currentTeamPiece
                if pieceToRemove:
                    currentTeamClone = []
                    for currentTeamPiece in self.currentTeam:
                        if currentTeamPiece != pieceToRemove:
                            currentTeamClone.append(currentTeamPiece)
                else:
                    currentTeamClone = self.currentTeam

                #If there is a valid move, return False
                if not king.isInCheck(self.otherTeam,currentTeamClone):
                    piece.setCoordinates(previousCoordinates)
                    return False
                piece.setCoordinates(previousCoordinates)
        #If program has gotten here, it means the other team has no moves and it is checkmate
        return True


    def movesCanMakeWithCheck(self,piece):
        #Putting this in ChessRunner because otherwise we would have to modify all the current movesCanMake methods
        movesCanMakeWithCheck = []
        movesCanMake = piece.movesCanMake(self.currentTeam,self.otherTeam)

        #Adding castle moves for king
        if piece.getType() == 'King':
            movesCanMake += piece.castleMoves(self.currentTeam,self.otherTeam)

        #For each move, test if it would put the king in check
        for move in movesCanMake:
            previousCoordinates = piece.getCoordinates()
            piece.setCoordinates(move)

            king = self.currentTeam[0]
            pieceToRemove = False

            #Simulating removing a piece
            for otherPiece in self.otherTeam:
                if piece.getCoordinates() == otherPiece.getCoordinates():
                    pieceToRemove = otherPiece
            
            if pieceToRemove:
                otherTeamClone = []
                for otherPiece in self.otherTeam:
                    if otherPiece != pieceToRemove:
                        otherTeamClone.append(otherPiece)
            else:
                otherTeamClone = self.otherTeam

            #If move wouldn't put king in check, it's a valid move            
            if not king.isInCheck(self.currentTeam,otherTeamClone):
                movesCanMakeWithCheck.append(move)
            piece.setCoordinates(previousCoordinates)
        return movesCanMakeWithCheck
                

    #To start new game
    def reset(self):
        #Waits for a click of the reset or quit button
        self.gui.reset()
        #Undraws pieces on the board
        for piece in self.whitePieces+self.blackPieces:
            piece.kill()

        #Resets pieces lists
        self.createPieces()

        #Draw new pieces and set initial variables
        for piece in self.whitePieces+self.blackPieces:
            piece.drawPiece(self.gui)
        self.checkmate = False
        self.currentTeam = self.whitePieces
        
           
        
    def createPieces(self):

        #Create pieces for both teams
        self.whitePieces = []
        self.whitePieces.append(King('white'))
        self.whitePieces.append(Queen('white'))
        self.whitePieces.append(Bishop('white',2,7))
        self.whitePieces.append(Bishop('white',5,7))
        self.whitePieces.append(Knight('white',1,7))
        self.whitePieces.append(Knight('white',6,7))
        self.whitePieces.append(Rook('white',0))
        self.whitePieces.append(Rook('white',7))

        self.blackPieces = []
        self.blackPieces.append(King('black'))
        self.blackPieces.append(Queen('black'))
        self.blackPieces.append(Bishop('black',2,0))
        self.blackPieces.append(Bishop('black',5,0))
        self.blackPieces.append(Knight('black',1,0))
        self.blackPieces.append(Knight('black',6,0))
        self.blackPieces.append(Rook('black',0))
        self.blackPieces.append(Rook('black',7))

        for i in range(8):
            self.whitePieces.append(Pawn('white',i,6))
            self.blackPieces.append(Pawn('black',i,1))

        
    def pieceOnSquare(self,pieces,square):
        #Given a team, will loop through team and see if any pieces' positions are on the given square
        for piece in pieces:
            if piece.getX() == square[0] and piece.getY() == square[1]:
                return piece
        return False

    def closeWindow(self):
        self.gui.closeWindow()

    def getTeamString(self):
        if self.currentTeam == self.whitePieces:
            return 'White'
        else:
            return 'Black'
        
    def getOtherTeamString(self):
        if self.otherTeam == self.whitePieces:
            return 'White'
        else:
            return 'Black'
    
    def printMoveMessage(self,piecesInvolvedInMove,isCastleMove):
        #To map number coordinates to chess coordinates
        yCoordinates = ['8','7','6','5','4','3','2','1']
        xCoordinates = ['a','b','c','d','e','f','g','h']

        pieceThatMoved = piecesInvolvedInMove[0]

        if isCastleMove:
            message = self.getTeamString()+" castled "
            if piecesInvolvedInMove[1] == pieceThatMoved.getRookLeft(self.currentTeam):
                message += "queenside"
            else:
                message += "kingside"
        else:
            message = self.getTeamString()+" "+pieceThatMoved.getType().lower()+" moved to " +\
                      xCoordinates[pieceThatMoved.getX()]+yCoordinates[pieceThatMoved.getY()]
            #If piece was taken
            if len(piecesInvolvedInMove) > 1:
                pieceTaken = piecesInvolvedInMove[1]
                
                message += " and took "+self.getOtherTeamString().lower()+" "+pieceTaken.getType().lower()
        self.gui.printMoves(message)
Пример #2
0
 def __init__(self):
     self.gui = ChessGUI()
     self.createPieces()
     self.checkmate = False