Hello, Everyone. First of all, Happy New Year 2017. In this year, I sincerly hope success for you, for your friends and family members. This article is going to discuss how python enables us to materialize our ideas into a quick reality by taking chess as an example.

Coming to the point, we all love the chess game. It is a beautiful game with a lot of brain work needed. Openings, Middle games and Endgames are always tough to master. In the 21st century, we have powerful chess engines those can compete with world’s best players. Have you ever thought how the chess game is modeled on a computer?. How pieces are looked underneath and what abstraction does calculate everything. The beauty of mathematics and programming language like Python makes it easy to implement any given problem in an elegant way. This is not a tutorial to build a chess engine. But this is the building block of any chess game.

The code for this tutorial is always available at this link

https://github.com/narenaryan/ChessMoves

### Objective

The main motto of this article is to design a program which actually takes the input of a chess notation and returns all possible moves for a given piece. For example, “What are the all possible moves of a Knight which is stationed on “g2”. It should return all possible moves from that location.

- e1
- e3
- f4
- h4

For this we need:

- ChessBoard
- Pieces

### Introduction

A chessboard is a 8 * 8 matrix. It has a notation from A-H and 1-8. Here (1-8) are rows and (A-H) are columns. We always refer the position of a chess piece by its chess notation. For example “e4” means 4th row, 5th column of the 8 * 8 matrix.

In Python, we can create a chessboard with one line.

>>> chessBoard = [[1] * 8 for i in xrange(8)]

This actually creates a list of lists with exactly 8 elements like this

>>> print chessBoard [[1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1]]

Now we have a chessboard. Let us start modeling the pieces and their moves.

Before going into the pieces, we need to think about something. As I told, rows and columns are in 1-8 & A-H notation but not in (0-n) notation of a matrix. So we should write a conversion formulae for translating chess notation to actual matrix index notation.

>>> chess_map_from_alpha_to_index = { "a" : 0, "b" : 1, "c" : 2, "d" : 3, "e" : 4, "f" : 5, "g" : 6, "h" : 7 }

>>> chess_map_from_index_to_alpha = { 0: "a", 1: "b", 2: "c", 3: "d", 4: "e", 5: "f", 6: "g", 7: "h" }

I here discuss 4 important chess pieces. You can implement for others in a similar fashion.

- Knight (Horse)
- Rook (Elephant)
- Bishop (Camel)
- Queen

I presume all know the rules of movement of each piece. If not please refer this short intro. https://en.wikipedia.org/wiki/Chess_piece#Moves_of_the_pieces

### Knight

Now let us start with the Knight. We all know the Knight moves in an L shape path in all possible directions. First, we can assume a Knight is in the center. Then just pick up all possible positions of the matrix where knight can move to. Let us think the initial position of the knight is at D4. Then the matrix diagram would be like this

It means the coordinates of the neighboring moves of a knight can be easily put down into few mathematical equations. By careful observation, we can come to know that all the moves are in this form.

All the below calculations for the given index gives the neighbor co-ordinates. If i is row index and j is column index, then

- (i + 2) , (j – 1)
- (i – 1), (j + 2)
- (i – 2), (j – 1)
- (i + 2), (j + 1)
- (i + 1), (j + 2)
- (i – 1), (j + 1)
- (i + 1), (j – 1)
- (i – 2), (j + 1)

Now if we write a python function with the given details

def getKnightMoves(pos, chessBoard): """ A function(positionString, board) that returns the all possible moves of a knight stood on a given position """ column, row = list(pos.strip().lower()) row = int(row) - 1 column = chess_map_from_alpha_to_index[column] i,j = row, column solutionMoves = [] try: temp = chessBoard[i + 1][j - 2] solutionMoves.append([i + 1, j - 2]) except: pass try: temp = chessBoard[i + 2][j - 1] solutionMoves.append([i + 2, j - 1]) except: pass try: temp = chessBoard[i + 2][j + 1] solutionMoves.append([i + 2, j + 1]) except: pass try: temp = chessBoard[i + 1][j + 2] solutionMoves.append([i + 1, j + 2]) except: pass try: temp = chessBoard[i - 1][j + 2] solutionMoves.append([i - 1, j + 2]) except: pass try: temp = chessBoard[i - 2][j + 1] solutionMoves.append([i - 2, j + 1]) except: pass try: temp = chessBoard[i - 2][j - 1] solutionMoves.append([i - 2, j - 1]) except: pass try: temp = chessBoard[i - 1][j - 2] solutionMoves.append([i - 1, j - 2]) except: pass # Filter all negative values temp = [i for i in solutionMoves if i[0] >=0 and i[1] >=0] allPossibleMoves = ["".join([chess_map_from_index_to_alpha[i[1]], str(i[0] + 1)]) for i in temp] allPossibleMoves.sort() return allPossibleMoves

We need to pass the position string and chess board to this function and it returns all possible moves in form of a string.

>>> print getKnightMoves("D4", chessBoard) [b3, b5, c2, c6, e2, e6, f3, f5]

### Rook

Rook moves in straight lines. It means it can move either horizontally or vertically. The logic for the movement is different from the Knight. So we need to observe what factors we need to collect to model the movements of a Rook.

In chess terminology Rook can move on Rank(row) and File(column). The Rook which is placed at” E6″ can move across 6th Rank and E file. So all possible moves are:

- E1, E2, E3, E4, E5, E7, E8, A6, B6, C6, D6, F6, G6, H6

Now in order to model it programmatically, we take end points as reference and by excluding the existing index we can compute all possible points in matrix. So let us define a function called **getRookMoves()**

def getRookMoves(pos, chessBoard): column, row = list(pos.strip().lower()) row = int(row) - 1 column = chess_map_from_alpha_to_index[column] i,j = row, column solutionMoves = [] # Compute the moves in Rank for j in xrange(8): if j != column: solutionMoves.append((row, j)) # Compute the moves in File for i in xrange(8): if i != row: solutionMoves.append((i, column)) solutionMoves = ["".join([chess_map_from_index_to_alpha[i[1]], str(i[0] + 1)]) for i in solutionMoves] solutionMoves.sort() return solutionMoves

>>> getRookMoves("E6", chessBoard) ['a6', 'b6', 'c6', 'd6', 'e1', 'e2', 'e3', 'e4', 'e5', 'e7', 'e8', 'f6', 'g6', 'h6']

**argparse**for making a command line application. We are going to print the JSON string for other application to make use of it.

import argparse, json parser = argparse.ArgumentParser() parser.add_argument("-p", "--piece", help="chess piece name: ex- rook, knight, pawn etc") parser.add_argument("-l", "--location", help="chess notation string: ex- E4, D6 etc") args = parser.parse_args() piece = args.piece.strip().lower() location = args.location.strip() # According to the type of piece adjust function if (piece == "rook"): print json.dumps({"piece":piece, "current_location": location, "moves": getRookMoves(location, chessBoard)}) elif (piece == "knight"): print json.dumps({"piece":piece, "current_location": location, "moves": getKnightMoves(location, chessBoard)})