skip to content
Stylized letter A in teal with pink sparkle accents Khalid Abuhakmeh

Rock, Paper, Scissors, Lizard, Spock II: Wrath Of Neo4j

/ 2 min read

Found this post helpful?

Buy me a coffee
Table of Contents

In my previous post, I wrote a C# game engine for the game Rock, Paper, Scissors, Lizard, Spock. I kept looking at the image describing the game and it began to look familiar. Where have I seen this before?

Rules Neo4j

Oh yeah… Neo4J and it’s amazingly descriptive UI. Could I develop a graph and query the result of any match? Let’s see if we can.

Setup

We first need to build the graph. We need to be more descriptive than the original image when describing the nodes and their relationships. We have 5 nodes: Rock, Paper, Scissors, Lizard, Spock. The relationships are Win, Lose, and Tie. This is what our Neo4J Cypher script will look like.

// Create a node
CREATE (Rock:Throw {name: "Rock"})
CREATE (Paper:Throw {name: "Paper"})
CREATE (Scissors:Throw {name: "Scissors"})
CREATE (Lizard:Throw {name: "Lizard" })
CREATE (Spock:Throw {name: "Spock"})
CREATE
(Rock)-[:Win]->(Scissors),
(Rock)-[:Win]->(Lizard),
(Rock)-[:Lose]->(Paper),
(Rock)-[:Lose]->(Spock),
(Paper)-[:Win]->(Rock),
(Paper)-[:Win]->(Spock),
(Paper)-[:Lose]->(Scissors),
(Paper)-[:Lose]->(Lizard),
(Scissors)-[:Win]->(Paper),
(Scissors)-[:Win]->(Lizard),
(Scissors)-[:Lose]->(Spock),
(Scissors)-[:Lose]->(Rock),
(Lizard)-[:Win]->(Spock),
(Lizard)-[:Win]->(Paper),
(Lizard)-[:Lose]->(Scissors),
(Lizard)-[:Lose]->(Rock),
(Spock)-[:Win]->(Scissors),
(Spock)-[:Win]->(Rock),
(Spock)-[:Lose]->(Paper),
(Spock)-[:Lose]->(Lizard),
(Rock)-[:Tie]->(Rock),
(Scissors)-[:Tie]->(Scissors),
(Paper)-[:Tie]->(Paper),
(Lizard)-[:Tie]->(Lizard),
(Spock)-[:Tie]->(Spock)

I really do love the descriptive nature of Cypher. It is really awesome. When we execute this script we get this result.

Playing The Game

To play the game we need to know which nodes we are traveling from and then understand the relationship between them. This is what the query looks like. In our example we just pick the two throws by name: Rock and Paper.

// Query
Match (from:Throw {name:"Rock"}), (to:Throw {name:"Paper"}), path = (from)-[result]->(to) return type(result) as Result

This is what we get when we execute this query. Crap, we lost!

Query 1

What about Rock versus Scissors?

// Query
Match (from:Throw {name:"Rock"}), (to:Throw {name:"Scissors"}), path = (from)-[result]->(to) return type(result) as Result
Win

Yay, we won! What about ties?

// Query
Match (from:Throw {name:"Rock"}), (to:Throw {name:"Rock"}), path = (from)-[result]->(to) return type(result) as Result
iIe

Hey, at least we survive to play another game.

Conclusion

This is a really interesting use case for a graph database, and it is really fun to explore how to get a game engine running in a few lines of cypher script. It is worth comparing my C# implementation to this one and seeing which is you prefer, I know I would lean towards this post’s solution since this can support multiple players in a single game while my C# solution is limited to two.

Related Posts