Final

Introduction

Hello, and welcome to the final for Let's Learn Software Development with Python! In this challenge will be developing a class that simulates the game-play of chess.

Chess requires critical thinking, analytical skills, and the ability to anticipate and react to your opponent's moves. And just like chess, this final will challenge you with the goal of making you a better programmer. Having played the game is not necessary, however having some passing knowledge of the game will be helpful in this project, please refer to this chess.com tutorial on how to play the game.

These questions are potentially on the harder side, however we have high expectations of you, and hope you will take it slow, think things out, try different pieces of code, and eventually reach a solution.

Chess board with algebraic notation

For your reference, here is the layout of a chess board. Algebraic notation represents a tile on the board. For example 'h8' is the top right in the image and 'd4' is near the center. This notation is composed of two parts, rank and file. Rank refers to the first character and is in the range [a,h]. File refers to the second character and is in the range [1,8].

Good luck!

Q1

This two part question will aim to place chess pieces on a board. The method place_piece is part of a Chessboard class. If you get stuck, use the hint at the bottom of this question, it include the entire code surrounding this method.

There is already quite a bit of helper code available to you. Here are some notes about them:

  • Classes for piece creation: {Pawn, Rook, Bishop, Knight, King, Queen} exist. They take (player: Chessplayer, algebraic_notation: str) as arguments.
  • self.board is a list of lists where values can be either None or a Chesspiece object. One can get to tiles on the board by indexing into it, such as self.board[0][7]
  • If a piece is created such as piece = Pawn(player, 'a1'), and then one looks on the board for it, it will be found at self.board[0][7] instead of self.board[0][0] as one might expect. Please use piece.rank() and piece.file() instead of integer indexing, these functions will correctly map algebraic notation to a position on the board

The parameters are as such

  • piece_name: enum for the piece, such as Piece.PAWN and Piece.ROOK
  • algebraic_notation: string for the position on the board, such as 'a1' and 'c3'
  • player: an object of type Chessplayer

Q1a.

Please fill out the method place_piece This is the first part of this method. Here, we are only looking to instantiate the correct object and place it on the board. This function will be called multiple times to set up a chess board.

Expect to

  • instantiate the piece with the correct Chesspiece class
  • return the instantiated object

Assume any call to this function is unreliable. If any of these fail, the piece shouldn't be placed on the board. That means to say, you should check that:

  • algebraic_notation is valid (a1-h8)
  • piece_name is one of {Piece.PAWN, Piece.ROOK, Piece.BISHOP, Piece.KNIGHT, Piece.KING, Piece.QUEEN}
  • (player will always be valid)

piece_name:

algebraic_notation:

player:

Q1b.

This is a continuation of the previous question, now we aim to place a piece on the board. Please re-use code you used to create the object. Then, find the correct place to put the piece on the board. A return object is no longer necessary as a reference should now be in the board.

Expect to

  • place the piece on the board

Assume any call to this function is unreliable. If any of these fail, the piece shouldn't be placed on the board. That means to say, you should check that:

  • The board is empty at the tile it will we placed
  • The piece is put on the correct tile

piece_name:

algebraic_notation:

player:

Q2

Please fill out the function move. Use the comments in the code to help determine what steps should be taken.

Assume any call to this function is unreliable. If any of these fail, the board shouldn't change. That means to say, you should check that:

  • algebraic_notation for move_from and move_to are valid (a1-h8)
  • a piece exists atmove_from
  • the piece can move naturally following normal chess rules (i.e. a bishop shouldn't be able to jump over a pawn)
  • the piece color matches the player color
  • (player will always be valid)

We are already providing some helper methods baked into the Chessboard and Piece classes for you to use, these are listed below:

  • self.get_piece(algebraic_notation: str) returns None if no piece found, otherwise returns the piece at that tile
  • self.get_valid_moves(player: Chesslayer, piece: Chesspiece) returns a list of lists of algebraic notation tiles a piece can move to given the pieces type and current position; these are valid positions that considers the dimensions of the board, the players own pieces, and the opponents pieces
  • piece.update_position(algebraic_notation: str) updates a pieces knowledge of where it is located on the board
  • piece.rank() and piece.file() are helpful again for indexing into self.board

player:

piece:

move_from:

move_to: