Building a Chess Engine Part 1

Building a playable version of chess for your console with python 3

Ben Bellerose
8 min readOct 29, 2021

Hi everyone this will be the first instalment in my tutorial series for building a chess engine. This lesson will focus on building a version of the game chess, that is playable in your console using python 3.

Game Board

The first thing we want to do is create the board that the game is played on. Chess is played on an 8x8 board where the x-axis of the board is notated from A-H and the y-axis is notated from 1–8.

Chess has 6 unique pieces, in our game we are going to encode each piece numerically as follows:

  • Pawn = 1 (8 per player)
  • Knight = 2 (2 per player)
  • Bishop = 3 (2 per player)
  • Rook = 4 (2 per player)
  • Queen = 5 (1 per player)
  • King = 6 (1 per player)

Chess is a two-player game where each player gets their own set of pieces. In order to easily determine which player each piece belongs to we are going to encode our players like so:

  • Black = -1
  • White = 1
  • Empty = 0

This way our board will look like this when fully encoded.

Now that we can visualize what our board looks like and know how we’re going to encode the pieces we can begin to build the game. To start this we’re going to build a “Chess” class to store our game's state.

In order to make this game more useful, we will allow users to load in different game states using Extended Position Description’s (EPD).

To make the game more user-friendly we will have to make a “display” function. This “display” function will take our game state and display it in a user-friendly format.

Pieces

Now that we can create our board and load different game states we need to build in some functionality. First were going to start with the movement rules of every piece. Each piece has a different set of valid moves, because of this we will create a separate class for each. By doing this we will have different objects that we can use to build our game. In each object, we will store its:

  • notation (used in our game log)
  • numeric value

These classes will also contain a generator function that will determine all valid moves for the desired piece at its current position.

Let’s start off with the pawn, a pawn can only move forward. The pawn can move up to two squares on its initial move, after its initial move it can only move one square. The pawn is only able to capture an opponent that is diagonally in front of it.

The knight moves in an “L” shape, it moves two squares in the X or Y axis and one square on the opposite axis. The knight can capture an opponent's piece if it is on the square the knight is moving to.

Available Knight Moves

The bishop moves diagonally as many squares as it wants, assuming there is nothing in its path. If there is an opponent in its path it can capture that opponent. When an opponent is captured the bishop will stop moving on that square.

Available Bishop Moves

The rook moves in straight lines as many squares as it wants, assuming there is nothing in its path. If there is an opponent in its path it can capture that opponent. When an opponent is captured the rook will stop moving on that square.

Available Rook Moves

The queen moves in straight and diagonal lines as many squares as it wants, assuming there is nothing in its path. If there is an opponent in its path it can capture that opponent. When an opponent is captured the queen will stop moving on that square.

Available Queen Moves

The king moves in a straight and diagonal line, but can only move one square at a time. If there is an opponent in its path it can capture that opponent. When an opponent is captured the king will stop moving on that square.

Available King Moves

Rules

Now that we know all the valid moves for our pieces, we can add in the remaining rules of chess. To enforce the rules of the game we are going to write a check state function that will check the state of the game to see if any rules have been activated.

The first rule we’re going to build is pawn promotion. Pawn promotion occurs when a player's pawn makes it to their opponent's side.

Pawn Promotion

If a pawn is found on the opposite player’s side we will ask the player what piece they would like to replace the pawn with. The player's options are queen, bishop, knight and rook. The player is able to double up on pieces if they choose. The player’s choice will then be noted in the game log using chess notation (English).

Ex. F1=Q

The fifty move rule occurs when there have been no captures by either player on their fiftieth move. When this rule occurs a player can request a draw. To build this rule we are going to check the last 100 moves for a “x” (captures notated by “x” in chess notation).

Ex. qh2xh4

If no “x” is found in the log we will ask the player if they would like to request a draw.

The seventy-five move rule occurs when there have been no captures by either player on their seventy-fifth move. When this rule occurs it is an automatic draw. To build this rule we are going to check the last 150 moves for an “x”. If no x is found in the log a draw will automatically be triggered.

The three-fold rule occurs when the game's current state has been seen three times. When this rule occurs a player can request a draw. To build this rule we are going to store the EPD of the game's current state in a hash table so that we can quickly reference how many times it has been seen. If the current state has been seen three times we will ask the player if they would like to request a draw.

The five-fold rule occurs when the game state has been seen five times. When this rule occurs it is an automatic draw. To build this rule we are going to check the EPD hash table, if the current state has been seen five times a draw will automatically be triggered.

A dead position occurs when no one can win the game based on the current state of the board. When this rule occurs it is an automatic draw. To build this rule we are going to check for the known dead positions. If any dead positions are found a draw will automatically be triggered.

A stalemate occurs when a player is unable to move and is not in check/checkmate. When this rule occurs it is an automatic draw. To build this rule we are going to check if both players are still able to move. If any player is unable to move a draw will automatically be triggered.

Checkmate occurs when the opponent’s king is able to be captured and can not escape. When this rule occurs it is an automatic win. To build this rule we are going to compute all possible moves on the board. If the opponent’s king is able to be captured each player’s moves will be compared to see if the capture can be blocked. If no possible blocks are found we will check if the king is able to escape. If the opponent is able to block the capture or the opponent’s king can escape, a check will be notated in the game log as “+”. If no blocks can be found and the opponent’s king can not escape a checkmate will be notated in the game log as “#” and a win will automatically be triggered.

Controls

Now that we have all our rules made we will want to build our controls. To control our game we need to allow players to move their pieces on the board. To make this more user-friendly we want the users to be able to input their desired moves using board notation.

Ex. A2 to A4

Because of this, we need to convert each input (board notation) to an X, Y coordinate so the program can find the desired positions on the board.

Ex. A2 = (0,6)

To do this conversion we are going to map the board notation to their appropriate coordinates.

Now that we can convert notation to a position we can write our program to move pieces. In order to enforce the part rules, we must verify each move using the piece’s available moves function. If the desired move is found in the piece’s available moves the move is considered valid and the function will return True. If the desired move is not found in the piece’s available moves the move will be considered invalid and the function will return False.

Now that we can verify the validity of a move we need to make the actual move function. If the desired move is valid the piece will be moved, the game state is updated and the function will return True. If the move is not valid the function will return False.

Thanks

And there you have it we have successfully created a chess game using python 3. Using the pieces we have created here you can now build a playable version of the game chess for your console. I hope you enjoyed reading part 1 of this series, you can check a full version of the code on my GitHub here.

References

--

--