def ResizeCanvas(self, canvasSize): # Save position of current pieces currentPositions = dict() for coordinate, piece in State().GetChessPiecePositions().items(): currentPositions[coordinate] = piece # Recalculate parameters Parameters().CalculateDimensionParam(canvasSize) self.canvas.config(width=canvasSize, height=canvasSize) for ChessType in Parameters().GetTypesOfChess(): ImgProcessor().ResizeChessPieceImages(ChessType) # Clear all objects self.ClearPiecesFromBoard() for object in self.chessboardObjects: self.canvas.delete(object) # Call functions to draw the chess board if State().GetChessType() == 'Chess': self.DrawChessBoard() elif State().GetChessType() == 'XiangQi': self.DrawXiangQiBoard() else: logging.error('Wrong "ChessType" when calling ResizeCanvas!') exit(1) # Add pieces to board for coordinate, chessPiece in currentPositions.items(): self.AddPieceToBoard(chessPiece['PlayerColor'], chessPiece['PieceType'], coordinate)
def BingMove(self, coordinate): ChessType = 'XiangQi' CurrentMove = self.GetCurrentMove() PlayerColor = CurrentMove.GetPlayerColor() isValidMove = False yCoordinateLim = (5, 9) direction = 1 if PlayerColor == Parameters().GetPlayerColors(ChessType)[0]: yCoordinateLim = (Parameters().GetChessBoardYArray(ChessType) - 1 - yCoordinateLim[1], Parameters().GetChessBoardYArray(ChessType) - 1 - yCoordinateLim[0]) direction = -1 if coordinate[0] == CurrentMove.GetStartPos( )[0] and coordinate[1] == CurrentMove.GetStartPos()[1] + direction: isValidMove = True elif coordinate[1] == CurrentMove.GetStartPos()[1] and abs( coordinate[0] - CurrentMove.GetStartPos()[0] ) == 1 and yCoordinateLim[0] <= coordinate[1] <= yCoordinateLim[1]: isValidMove = True if isValidMove: self.GetCurrentMove().SetEndPos(coordinate) return True return False
def __InitCanvasParameters(self): Parameters().CalculateDimensionParam() self.canvas.config(width=Parameters().GetCanvasSize(), height=Parameters().GetCanvasSize()) self.chessboardObjects = list() self.chesspiecesObjects = dict() self.active_square_objects = list() self.canvas.bind('<Button-1>', self.lmb_callback)
def LoadFromFile(): filename = filedialog.askopenfilename( initialdir='.', filetypes=(('Comma Separated Values', '*.csv*'), ('all files', '*.*'))) if filename != '': data = dict() file = open(filename, 'r') lines = file.read().split('\n') self.CaptionPanel.delete(0, tkinter.END) self.CaptionPanel.insert(0, lines[0]) for line in lines[1:]: if line: x, y, piece = line.split(',') data[(int(x), int(y))] = piece file.close() # Get types of chess pieces chess_piece_types = set() for chess_piece in data.values(): chess_piece_types.add(chess_piece.split('_')[1]) # Find out what type of chess it is ChessType = 'Chess' for piece in chess_piece_types: if ChessType == 'Chess' and piece not in Parameters( ).GetTypesOfChessPieces('Chess'): ChessType = 'XiangQi' # Change chess type if neccessary if ChessType != State().GetChessType(): self.chess_type_var.set(ChessType) self.ChangeChessType(ChessType) # Update chess pieces self.ChessBoard.ClearPiecesFromBoard() for coordinate, piece in data.items(): if 0 <= coordinate[0] < Parameters().GetChessBoardXArray( ChessType) and 0 <= coordinate[1] < Parameters( ).GetChessBoardYArray(ChessType): self.ChessBoard.AddPieceToBoard( piece['PlayerColor'], piece['PieceType'], coordinate) else: msg = 'Coordinate ' + str( coordinate ) + ' is out of range!\nThe piece will be ignored.' messagebox.showerror('Warning', msg) State().ClearMoveList() self.ChessBoard.RemoveHighlights()
def AddMenu(self): ChessType = State().GetChessType() PlayerColors = Parameters().GetPlayerColors(ChessType) TypesOfChessPieces = Parameters().GetTypesOfChessPieces(ChessType) State().SetGameIsOngoing(True) var = tkinter.StringVar(value='deselect') def callback(): if State().GetSelectedPieceToAddToBoard() != var.get(): if var.get() != 'deselect': State().ClearMoveList() self.ChessBoard.RemoveHighlights() State().SetSelectedPieceToAddToBoard(var.get()) if var.get() == 'deselect': State().SetGameIsOngoing(True) else: State().SetGameIsOngoing(False) for piece in TypesOfChessPieces: RadiobtnFrame = tkinter.Frame(self.frame) RadiobtnFrame.pack(anchor='w') for PlayerColor in PlayerColors: ChessPieceString = PlayerColor + '_' + piece img = ImgProcessor().GetImage(ChessType, ChessPieceString) LongerSide = img.size[ 0] if img.size[0] > img.size[1] else img.size[1] ScalingFactor = self.__RadiobtnSize / LongerSide ScaledSize = (int(ScalingFactor * img.size[0]), int(ScalingFactor * img.size[1])) img = ImageTk.PhotoImage(img.resize(ScaledSize)) Radiobtn = tkinter.Radiobutton(RadiobtnFrame, command=callback, variable=var, value=ChessPieceString, image=img, indicatoron=0, width=self.__RadiobtnSize, height=self.__RadiobtnSize) Radiobtn.image = img Radiobtn.pack(side=tkinter.LEFT) tkinter.Radiobutton(self.frame, command=callback, variable=var, value='remove', text='Remove').pack(anchor='w') tkinter.Radiobutton(self.frame, command=callback, variable=var, value='deselect', text='Deselect').pack(anchor='w')
def lmb_callback(self, event): ChessType = State().GetChessType() CellSize = Parameters().GetCellSize(ChessType) BoardXStart, BoardXEnd = Parameters().GetBoardXLimits(ChessType) BoardYStart, BoardYEnd = Parameters().GetBoardYLimits(ChessType) # Handle events within the chessboard if BoardXStart < event.x < BoardXEnd and BoardYStart < event.y < BoardYEnd: x = int((event.x - BoardXStart) / CellSize) y = int((event.y - BoardYStart) / CellSize) # Check if x,y are allowed values if x < 0: x = 0 if x >= Parameters().GetChessBoardXArray(ChessType): x = Parameters().GetChessBoardXArray(ChessType) - 1 if y < 0: y = 0 if y >= Parameters().GetChessBoardYArray(ChessType): y = Parameters().GetChessBoardYArray(ChessType) - 1 coordinate = (x, y) if State().IsGameOngoing(): MoveHandler().Process(coordinate) else: self.ChangePieceOnBoard(coordinate)
def AddPieceToBoard(self, PlayerColor, PieceType, coordinate): State().AddChessPieceToPosition(PlayerColor, PieceType, coordinate) ChessType = State().GetChessType() img = ImgProcessor().GetPhotoImage(ChessType, PlayerColor + '_' + PieceType) self.chesspiecesObjects[coordinate] = [ self.canvas.create_image(Parameters().GetCellCenter( ChessType, coordinate), image=img), img ]
def DrawChessBoard(self): ChessType = 'Chess' BoardMargin = Parameters().GetBoardMargin() BoardSize = Parameters().GetBoardSize() CellSize = Parameters().GetCellSize(ChessType) TextMargin = Parameters().GetTextMargin(ChessType) # Draw black and white squares self.chessboardObjects.append( self.canvas.create_rectangle(BoardMargin, BoardMargin, BoardMargin + BoardSize, BoardMargin + BoardSize, fill='white', width=4)) for i in range(Parameters().GetChessBoardXArray(ChessType)): for j in range(Parameters().GetChessBoardYArray(ChessType)): cell_color = 'white' if (i + j) % 2 == 0 else 'black' x = BoardMargin + i * CellSize y = BoardMargin + j * CellSize self.chessboardObjects.append( self.canvas.create_rectangle(x, y, x + CellSize, y + CellSize, fill=cell_color, width=0)) # Insert alphabets and numbers for notation alphabets = ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h') for i in range(Parameters().GetChessBoardXArray(ChessType)): self.chessboardObjects.append( self.canvas.create_text(BoardMargin + (i + 0.5) * CellSize, BoardMargin + BoardSize + TextMargin, text=alphabets[i], font=12)) self.chessboardObjects.append( self.canvas.create_text(BoardMargin - TextMargin, BoardMargin + BoardSize - (i + 0.5) * CellSize, text=i + 1, font=12)) self.chessboardObjects.append( self.canvas.create_text(BoardMargin + (i + 0.5) * CellSize, BoardMargin - TextMargin, text=alphabets[i], font=12, angle=180)) self.chessboardObjects.append( self.canvas.create_text(BoardMargin + BoardSize + TextMargin, BoardMargin + BoardSize - (i + 0.5) * CellSize, text=i + 1, font=12, angle=180))
def ShuaiMove(self, coordinate): ChessType = 'XiangQi' CurrentMove = self.GetCurrentMove() PlayerColor = CurrentMove.GetPlayerColor() isValidMove = False xCoordinateLim = (3, 5) yCoordinateLim = (0, 2) if PlayerColor == Parameters().GetPlayerColors(ChessType)[0]: yCoordinateLim = (Parameters().GetChessBoardYArray(ChessType) - 1 - yCoordinateLim[1], Parameters().GetChessBoardYArray(ChessType) - 1 - yCoordinateLim[0]) if abs(coordinate[0] - CurrentMove.GetStartPos( )[0]) == 1 and coordinate[1] == CurrentMove.GetStartPos( )[1] and xCoordinateLim[0] <= coordinate[0] <= xCoordinateLim[1]: isValidMove = True elif abs(coordinate[1] - CurrentMove.GetStartPos( )[1]) == 1 and coordinate[0] == CurrentMove.GetStartPos( )[0] and yCoordinateLim[0] <= coordinate[1] <= yCoordinateLim[1]: isValidMove = True else: EnemyKing = State().GetChessPieceAtPosition(coordinate) if EnemyKing != None and EnemyKing[ 'PlayerColor'] != CurrentMove.GetPlayerColor( ) and EnemyKing['PieceType'] == 'shuai': isBlocked = False CheckRange = (coordinate[1], CurrentMove.GetStartPos()[1]) CheckRange = (min(CheckRange), max(CheckRange)) for i in range(CheckRange[0] + 1, CheckRange[1]): if State().PieceExistsAtPosition((coordinate[0], i)): isBlocked = True break if not isBlocked: isValidMove = True if isValidMove: self.GetCurrentMove().SetEndPos(coordinate) return True return False
def __init__(self): root = Parameters().GetRoot() self.PieceToPromoteTo = None self.PromotionWindow = tkinter.Toplevel(root) self.PromotionWindow.title('Promotion') def callback(ChosenPiece): self.PieceToPromoteTo = ChosenPiece self.PromotionWindow.destroy() for PieceType in Parameters().GetTypesOfChessPieces( 'Chess'): if PieceType != 'king' and PieceType != 'pawn': ImgName = color + '_' + PieceType ButtonSize = Parameters().GetCellSize('Chess') img = ImgProcessor().GetPhotoImage( 'Chess', ImgName) bt = tkinter.Button( self.PromotionWindow, image=img, command=lambda s=PieceType: callback(s), width=ButtonSize, height=ButtonSize) bt.image = img bt.pack(side=tkinter.LEFT) root.wait_window(self.PromotionWindow)
def ShiMove(self, coordinate): ChessType = 'XiangQi' CurrentMove = self.GetCurrentMove() PlayerColor = CurrentMove.GetPlayerColor() isValidMove = False xCoordinateLim = (3, 5) yCoordinateLim = (0, 2) if PlayerColor == Parameters().GetPlayerColors(ChessType)[0]: yCoordinateLim = (Parameters().GetChessBoardYArray(ChessType) - 1 - yCoordinateLim[1], Parameters().GetChessBoardYArray(ChessType) - 1 - yCoordinateLim[0]) if (abs(coordinate[0] - CurrentMove.GetStartPos()[0]) == 1 and abs(coordinate[1] - CurrentMove.GetStartPos()[1]) == 1 and xCoordinateLim[0] <= coordinate[0] <= xCoordinateLim[1] and yCoordinateLim[0] <= coordinate[1] <= yCoordinateLim[1]): isValidMove = True if isValidMove: self.GetCurrentMove().SetEndPos(coordinate) return True return False
def XiangMove(self, coordinate): ChessType = 'XiangQi' CurrentMove = self.GetCurrentMove() PlayerColor = CurrentMove.GetPlayerColor() isValidMove = False yCoordinateLim = (0, 4) if PlayerColor == Parameters().GetPlayerColors(ChessType)[0]: yCoordinateLim = (Parameters().GetChessBoardYArray(ChessType) - 1 - yCoordinateLim[1], Parameters().GetChessBoardYArray(ChessType) - 1 - yCoordinateLim[0]) if (abs(coordinate[0] - CurrentMove.GetStartPos()[0]) == 2 and abs(coordinate[1] - CurrentMove.GetStartPos()[1]) == 2 and yCoordinateLim[0] <= coordinate[1] <= yCoordinateLim[1]): midpoint = ((coordinate[0] + CurrentMove.GetStartPos()[0]) // 2, (coordinate[1] + CurrentMove.GetStartPos()[1]) // 2) if State().GetChessPieceAtPosition(midpoint) == None: isValidMove = True if isValidMove: self.GetCurrentMove().SetEndPos(coordinate) return True return False
def GetPlayerColorFromYCoordinate(self, yCoordinate): if yCoordinate == 7: return Parameters().GetPlayerColors()[0] if yCoordinate == 0: return Parameters().GetPlayerColors()[1] return None
def SetupLogging(): logDirName = 'log' if not os.path.exists(logDirName): os.makedirs(logDirName) logging.basicConfig( filename=logDirName + os.path.sep + date.today().strftime('%Y%m%d') + '.log', encoding='utf-8', format='%(asctime)s %(levelname)-8s %(module)-30s: %(message)s', level=logging.INFO, datefmt='%Y-%m-%d %H:%M:%S', ) if __name__ == '__main__': SetupLogging() logging.info('Program has started') Parameters() State() ImgProcessor() root = tkinter.Tk() root.state('zoomed') Parameters().SetRoot(root) MainWindow = MainWindow(root) root.mainloop()
def AddHighlight(self, square): if square != 0: ChessType = State().GetChessType() linewidth = Parameters().GetHighlightLinewidth() color = Parameters().GetHighlightColor(ChessType) x, y = Parameters().GetCellCenter(ChessType, square) size = 0.5 * Parameters().GetCellSize(ChessType) length = 0.6 * size offset = 0.1 * linewidth # Top left corner self.active_square_objects.append( self.canvas.create_rectangle(x - size + offset, y - size + offset, x - size + length, y - size + linewidth, width=0, fill=color)) self.active_square_objects.append( self.canvas.create_rectangle(x - size + offset, y - size + offset, x - size + linewidth, y - size + length, width=0, fill=color)) # Top right corner self.active_square_objects.append( self.canvas.create_rectangle(x + size - offset, y - size + offset, x + size - length, y - size + linewidth, width=0, fill=color)) self.active_square_objects.append( self.canvas.create_rectangle(x + size - offset, y - size + offset, x + size - linewidth, y - size + length, width=0, fill=color)) # Bottom left corner self.active_square_objects.append( self.canvas.create_rectangle(x - size + offset, y + size - offset, x - size + length, y + size - linewidth, width=0, fill=color)) self.active_square_objects.append( self.canvas.create_rectangle(x - size + offset, y + size - offset, x - size + linewidth, y + size - length, width=0, fill=color)) # Bottom right corner self.active_square_objects.append( self.canvas.create_rectangle(x + size - offset, y + size - offset, x + size - length, y + size - linewidth, width=0, fill=color)) self.active_square_objects.append( self.canvas.create_rectangle(x + size - offset, y + size - offset, x + size - linewidth, y + size - length, width=0, fill=color))
def DrawXiangQiBoard(self): ChessType = 'XiangQi' BoardMargin = Parameters().GetBoardMargin() BoardSize = Parameters().GetBoardSize() CellSize = Parameters().GetCellSize(ChessType) TextMargin = Parameters().GetTextMargin(ChessType) BoardYStart, BoardYEnd = Parameters().GetBoardYLimits(ChessType) linewidth = 2 linelength = int(0.35 * CellSize) offset = 2 * linewidth # Draw horizontal lines for i in range(Parameters().GetChessBoardYArray(ChessType)): self.chessboardObjects.append( self.canvas.create_line( BoardMargin + CellSize - 0.5 * linewidth, BoardMargin + (i + 0.5) * CellSize, BoardMargin - CellSize + 0.5 * linewidth + BoardSize, BoardMargin + (i + 0.5) * CellSize, width=linewidth)) # Draw vertical lines for i in range(Parameters().GetChessBoardXArray(ChessType)): if i == 0 or i == Parameters().GetChessBoardXArray(ChessType) - 1: self.chessboardObjects.append( self.canvas.create_line(BoardMargin + (i + 1) * CellSize, BoardMargin + 0.5 * CellSize, BoardMargin + (i + 1) * CellSize, BoardMargin - 0.5 * CellSize + BoardSize, width=linewidth)) else: self.chessboardObjects.append( self.canvas.create_line(BoardMargin + (i + 1) * CellSize, BoardMargin + 0.5 * CellSize, BoardMargin + (i + 1) * CellSize, BoardMargin - 0.5 * CellSize + 0.5 * BoardSize, width=linewidth)) self.chessboardObjects.append( self.canvas.create_line( BoardMargin + (i + 1) * CellSize, BoardMargin + 0.5 * CellSize + 0.5 * BoardSize, BoardMargin + (i + 1) * CellSize, BoardMargin - 0.5 * CellSize + BoardSize, width=linewidth)) # Draw top 'X' self.chessboardObjects.append( self.canvas.create_line(BoardMargin + 0.5 * BoardSize - CellSize, BoardMargin + 0.5 * CellSize, BoardMargin + 0.5 * BoardSize + CellSize, BoardMargin + 2.5 * CellSize, width=linewidth)) self.chessboardObjects.append( self.canvas.create_line(BoardMargin + 0.5 * BoardSize - CellSize, BoardMargin + 2.5 * CellSize, BoardMargin + 0.5 * BoardSize + CellSize, BoardMargin + 0.5 * CellSize, width=linewidth)) # Draw bottom 'X' self.chessboardObjects.append( self.canvas.create_line(BoardMargin + 0.5 * BoardSize - CellSize, BoardMargin + BoardSize - 0.5 * CellSize, BoardMargin + 0.5 * BoardSize + CellSize, BoardMargin + BoardSize - 2.5 * CellSize, width=linewidth)) self.chessboardObjects.append( self.canvas.create_line(BoardMargin + 0.5 * BoardSize - CellSize, BoardMargin + BoardSize - 2.5 * CellSize, BoardMargin + 0.5 * BoardSize + CellSize, BoardMargin + BoardSize - 0.5 * CellSize, width=linewidth)) # Draw lines for 'pao' and 'bing' LHSCoordinates = list() RHSCoordinates = list() for i in (1, 7): for j in (2, 7): LHSCoordinates.append((i, j)) RHSCoordinates.append((i, j)) for j in (3, 6): for i in range(2, 9, 2): LHSCoordinates.append((i, j)) for i in range(0, 7, 2): RHSCoordinates.append((i, j)) for coordinate in LHSCoordinates: x, y = Parameters().GetCellCenter(ChessType, coordinate) self.chessboardObjects.append( self.canvas.create_line(x - offset, y - offset, x - linelength, y - offset, width=linewidth)) self.chessboardObjects.append( self.canvas.create_line(x - offset, y - offset, x - offset, y - linelength, width=linewidth)) self.chessboardObjects.append( self.canvas.create_line(x - offset, y + offset, x - linelength, y + offset, width=linewidth)) self.chessboardObjects.append( self.canvas.create_line(x - offset, y + offset, x - offset, y + linelength, width=linewidth)) for coordinate in RHSCoordinates: x, y = Parameters().GetCellCenter(ChessType, coordinate) self.chessboardObjects.append( self.canvas.create_line(x + offset, y - offset, x + linelength, y - offset, width=linewidth)) self.chessboardObjects.append( self.canvas.create_line(x + offset, y - offset, x + offset, y - linelength, width=linewidth)) self.chessboardObjects.append( self.canvas.create_line(x + offset, y + offset, x + linelength, y + offset, width=linewidth)) self.chessboardObjects.append( self.canvas.create_line(x + offset, y + offset, x + offset, y + linelength, width=linewidth)) # Add numbers for i in range(Parameters().GetChessBoardXArray(ChessType)): self.chessboardObjects.append( self.canvas.create_text(BoardMargin + (i + 1) * CellSize, BoardYStart - TextMargin, text=i + 1, font=12, angle=180)) self.chessboardObjects.append( self.canvas.create_text(BoardMargin + BoardSize - (i + 1) * CellSize, BoardYEnd + TextMargin, text=i + 1, font=12))