As previously mentioned, this project uses a chess engine called Stockfish. This is a powerful computer program that analyzes chess positions and generates a move or list of moves that it considers the strongest (depending on the selected difficulty level). To interface the rest of the code with the chess engine we use a library called Python Chess which communicates with it using the UCI (Universal Chess Interface) protocol. This protocol uses the algebraic chess notation for describing and recording the moves in a game, for example: e2e4, e7e5, e1g1 (white short castling), e7e8q (for promotion).
With the chess engine and Python Chess library we can internally keep track of the game states, validate the human player's moves as well as decide which move the robot will make. However, although these allow us to check if the player’s moves are valid, we must also take into account the possible errors we might get due to unstable lightning in the computer vision module, which could cause an incorrect move detection. For this, we created an additional function that uses the probability of the moves detected with the computer vision algorithm, which as previously indicated, are a list of the four squares that changed the most in the human player’s turn.
This “moveAnalysis” function uses the information of the detected squares to find the most probable move, checks its validity, and if it is valid returns a dictionary object with the move in UCI notation and the type of move it was, for example a capture or any of the special moves:
- Castling: In this case, the algorithm ensures that it is the king and rook moving, rather than two other pieces, for which it would throw an error. It then identifies whether the castling takes place on the short side (king) or long side (queen).
- En passant: This case is pretty straightforward, if a special “as it passes” pawn capture takes place, this is saved as a “Passant” type move.
- Pawn promotion: As mentioned in the Vision Module tutorial, in this case a GUI window pops up and prompts the user to choose which piece the user would like to promote and then it updates the chess piece accordingly.
However, in addition to these chess coordinates, we also need to generate the sequence the robot has to follow in order to make the move. This is done with the “sequenceGenerator” function which is especially important when it comes to capture moves, because in these, the robot must first move the captured piece out of the board and then make its move. This sequence is also used to update both the player and robot’s moves in the GUI but this will be explained in the interface module.