GraphGists

Chess board

This GraphGist will show how to set up a rich connected chessboard for later use by Neo4j-enabled application.

Let us start with the basics. We are going to create a classic 8x8 chessboard as described in Wikipedia article.

Creating Files

The files are labelled by the letters a to h from left to right from the white player’s point of view. So, let us create eight (:File) nodes with {letter:<letter>} as a property and connect them with (:File)-[:RIGHT]→(:File) relationships.

Let us have a look at the (:File) nodes and their connections:

MATCH (f:File) RETURN f

Creating Ranks

Now we are going to create eight rank nodes (:Rank) numbered from 1 to 8, with 1 being closest to the white player. Ranks are connected to each other using (:Rank)-[:TOP]→(:Rank) relationships.

Let us have a look at the (:Rank) nodes and their connections:

MATCH (r:Rank) RETURN r

Creating Squares

Creating 64 (:Square) nodes is easy, thanks to existing (:Rank) and (:File) nodes. Each square has a link to the corresponding rank (:Rank)←[:VERTICAL]-(:Square) and file (:File)←[:HORIZONTAL]-(:File). Also, each square inherits properties from rank and file nodes and has it’s own property {san} from a1 to h8, thus providing a standard notation called algebraic chess notation.

Let us have a look at the e4 square node (:Square{san:'e4'}) and their connection to corresponding rank and file nodes:

MATCH (r:Rank)<-[:VERTICAL]-(s:Square{san:"e4"})-[:HORIZONTAL]-(f:File) RETURN s,r,f

Interconnecting Squares

Now we will connect the squares of the board with relationships representing possible chess piece relocations. Each (:Square)-[:HOP]-(:Square) relationship has {type:<type>} and {length:<length>} properties.

First, we create all possible horizontal relationships. Chess pieces such as King, Queen and Rook can move in this direction.

Let us have a look at the d4 square node connected horizontally:

MATCH (s:Square{san:'d4'})-[h:HOP{type:'horizontal'}]-(q:Square) RETURN s,q,h

In a similar way we create possible vertical relationships. Chess pieces such as King, Queen, Rook and Pawn can move in this direction.

Let us have a look at the c4 square node connected vertically:

MATCH (s:Square{san:'c4'})-[h:HOP{type:'vertical'}]-(q:Square) RETURN s,q,h

We can now utilize existing horizontal and vertical [:HOP] relationships to easily create diagonal relationships between squares. Chess pieces such as King, Queen, Bishop and Pawn can move in this direction.

Let us have a look at the e5 square node connected diagonally:

MATCH (s:Square{san:'e5'})-[h:HOP{type:'diagonal'}]-(q:Square) RETURN s,q,h

Finally we need to create [:HOP] relationship for the very special chess piece - Knight. Again, we will use existing horizontal and vertical [:HOP] relationships to do it.

Let us have a look at the d5 square node and possible Knight jumps from it. We should not pay much attention to the relationship directions since Cypher allows us to build quieries in both ways.

MATCH (s:Square{san:'d5'})-[h:HOP{type:'knight'}]-(q:Square) RETURN s,q,h

Fun part

OK, we now have eight (:Rank) nodes, eight (:File) nodes and sixty four (:Square) nodes with a lot of different connections between them. How do we use them to get anything valuable?

Example 1: Let us calculate the total number of possible Bishop moves. We will query for all the [:HOP] relationships with the {type:'diagonal'} property. Since there are two Bishops on the board (light-squared and dark-squared) we need to divide the total number by two. Please note, we do not specifiy relationship direction in order to account for opposite direction moves such as a1h8 and h8a1.

MATCH (s:Square)-[h:HOP{type:'diagonal'}]-(q:Square) RETURN count(h)/2

Example 2: Below is the query to get all possible Queen moves from e4 square. It will show the longest moves first. Overall there are 27 possible moves. This is why Queen in the center of the board is the most powerful chess piece.

MATCH (s:Square{san:'e4'})-[h:HOP]-(q:Square) WHERE h.type <> 'knight' RETURN s.san+q.san, h.type, h.length ORDER BY h.length DESC

Example 3: Finding the shortest Knight tour from a1 to h8 square. It appears six moves are required for Knight to reach the opposite side of the board.

MATCH p=(s:Square{san:"a1"})-[:HOP*..6{type:"knight"}]-(b:Square{san:"h8"}) WITH p,nodes(p) AS n LIMIT 1 UNWIND n as nodes RETURN length(p),collect(nodes.san)

Obviously, these are just a few simple examples but one can build more sophisticated queries utilizing the power of Cypher and the graph theory. The chessboard described in this graph can be used as a fundamental part for other chess related graphs.

I would really love to get any feedback. If you found an error, have a suggestion or comment, please do not mind to hit me back.

This gist was created by Andrey Tutolmin