Displaying chess pieces on the chessboard

Now, let's turn our attention to displaying all the chess pieces on the chessboard.

First, we'll define a method named draw_single_piece, which draws a chess piece at the given position when it's given a position, and the character representing the chess piece as follows (see 4.03view.py):

def draw_single_piece(self, position, piece):
x, y = self.controller.get_numeric_notation(position)
if piece:
filename = "../pieces_image/{}_{}.png".format(piece.name.lower(), piece.color)
if filename not in self.images:
self.images[filename] = PhotoImage(file=filename)
x0, y0 = self.calculate_piece_coordinate(x, y)
self.canvas.create_image(x0, y0, image=self.images[filename],
tags=("occupied"), anchor="c")

The following is a description of the preceding code:

  • The images of the chess pieces are stored in a folder named pieces_image and are named with the chess piece's name in lowercase + _ + color.png format. So for instance, the black queen is saved by the name queen_black.png.
  • The images are added to the chessboard by using the canvas.create_image() method, which takes the x, y coordinates and a PhotoImage() object that relies on the location of the image file as its argument.
  • We used Tkinter's PhotoImage class to reference the .png files.
  • In addition to creating and displaying a chess piece on the chessboard, we also tagged them with a custom tag called occupied. Tagging is an important feature of the Canvas widget which lets us uniquely identify items placed on the Canvas widget.

We  used the following helper method in the preceding code (see 4.03view.py):

def calculate_piece_coordinate(self, row, col):
x0 = (col * DIMENSION_OF_EACH_SQUARE) + int(DIMENSION_OF_EACH_SQUARE / 2)
y0 = ((7 - row) * DIMENSION_OF_EACH_SQUARE) +
int(DIMENSION_OF_EACH_SQUARE / 2)
return (x0, y0)

We also define another helper method that returns the numeric notation for the position of a piece (see 4.03controller.py):

def get_numeric_notation(self, position):
return piece.get_numeric_notation(position)

This is just a wrapper around the following code from 4.03piece.py:

def get_numeric_notation(rowcol):
row, col = rowcol
return int(col)-1, X_AXIS_LABELS.index(row)

Now, it's time simply to call the preceding draw_single_piece method on all the chess pieces (4.03view.py):

def draw_all_pieces(self):
self.canvas.delete("occupied")
for position, piece in self.controller.get_all_pieces_on_chess_board():
self.draw_single_piece(position, piece)

A key aspect that you need to note here is that when we needed some data from the Model class, say, a dictionary containing all the chess pieces on the chessboard, we did not directly call the Model class for the data. Instead, we requested the controller get us the data from the model. The get_all_pieces_on_chess_board() controller method is simply a wrapper around the actual method from the Model class (see 4.03controller.py):

def get_all_pieces_on_chess_board(self):
return self.model.items()

Great! We now have the methods required to draw all the chess pieces on the chessboard. But merely defining them does not help. These methods need to be called from somewhere. Therefore, let's define a new method named start_new_game() and call it from the __init__ method of the View class, as follows (see 4.03view.py):

 def start_new_game(self):
self.controller.reset_game_data()
self.controller.reset_to_initial_locations()
self.draw_all_pieces()

In addition to calling the draw_all pieces() method, this method also resets the Model via calls to two wrapper controller methods (see 4.03controller.py):

def reset_game_data(self):
self.model.reset_game_data()

def reset_to_initial_locations(self):
self.model.reset_to_initial_locations()

The actual methods are defined in the Model class, as follows:

def reset_game_data(self):
captured_pieces = {'white': [], 'black': []}
player_turn = None
halfmove_clock = 0
fullmove_number = 1
history = []

def reset_to_initial_locations(self):
self.clear()
for position, value in START_PIECES_POSITION.items():
self[position] = piece.create_piece(value)
self[position].keep_reference(self)
self.player_turn = 'white'

The reset_game_data() method is simple. It just resets all the attributes of the Model class to their initial states.

The reset_to_initial_locations() method initializes all the chess piece locations to reflect the starting position of the game. This too should be self-explanatory if you are aware of the data structure that we discussed earlier.

Now, when you go ahead and run the code (see 4.03view.py), the chessboard should display all the chess pieces at the starting position of the game, as shown in the following screenshot:

This completes the current iteration. The next iteration will define the rules for the movement of the chess pieces on the chessboard. We need this part done before we can think of moving the chess pieces around.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.17.174.0