I wanted to start this post talking about a popular word guessing game, Semantle. In this single player word-guessing game, the player must correctly guess the hidden word. Every guess has to be a word. The game shows how semantically related your term is to the hidden word. It's not about the spelling, it's about the meaning. To indicate how close the guessed word is to the secret one, it uses a similarity system, where the maximum degree of similarity is 100 and the lowest is -100. There is also an indicator that tells how close you are from the hidden word in three different categories: cold, tepid and warm.
So, in this post I wanted to share with you all how we could create this kind of game with the use of Apache AGE, a graph extension for PostgreSQL, for our database. It wont be 100% similar to Semantle, we will do some modifications to it. But the main idea of the game will be the same. For this game, I would like to implement the same logic as the "Getting to Philosophy" phenomena that happens on Wikipedia when you click on the first link of an article and do the same thing on the subsequent ones until you find the Philosophy article. I actually address this phenomena in my previous blog.
Creating the Graph
To create the graph, we would need to type the following command on a postgres running instance:
-- Creating the Graph
SELECT ag_catalog.create_graph('Wikipedia');
NOTICE: graph "Wikipedia" has been created
create_graph
--------------
(1 row)
After this, you can search on Wikipedia for a word of your preference and follow it's path until Philosophy, adding vertices and edges to AGE with the following query:
-- (Word)-(...)->(Philosophy)
SELECT * FROM cypher('Wikipedia', $$
CREATE (:Article {name: 'Word'})-[:RELATED_TO]->
(:Article {name: '...'})-[:RELATED_TO]->
(:Article {name: '...'})-[:RELATED_TO]->
...
(:Article {name: '...'})-[:RELATED_TO]->
(:Article {name: 'Philosophy'})
$$) as (a agtype);
a
---
(0 rows)
Now, lets say that the word I chose is River. To get to Philosophy, the path from River to it passes by Science. And because I have already created a graph with the Science vertex, I will only add these new vertices i find in the path until I reach Science.
SELECT * FROM cypher('Wikipedia', $$
MATCH (v) WHERE v.name = 'Science' CREATE
(:Article {name: 'River'})-[:RELATED_TO]->
(:Article {name: 'Stream'})-[:RELATED_TO]->
(:Article {name: 'Body of water'})-[:RELATED_TO]->
(:Article {name: 'Water'})-[:RELATED_TO]->
(:Article {name: 'Inorganic compound'})-[:RELATED_TO]->
(:Article {name: 'Chemistry'})-[:RELATED_TO]->
(v)
$$) AS (a agtype);
How will the logic of the game work
When the player guesses a word, it will perform a query that will look something like this in cypher syntax:
MATCH (a)-[e:RELATED_TO*]-(b)
WHERE a.name = 'guessed_word' AND b.name = 'secret_word'
RETURN size(e)
Lets say that our player guessed the word Water. Then, to count how distant Water is from River, the following query is executed:
SELECT * FROM cypher('Wikipedia', $$
MATCH (a)-[e:RELATED_TO*]-(b)
WHERE a.name = 'Water' AND b.name = 'River'
RETURN size(e)
$$) AS (edge_count agtype);
edge_count
------------
3
(1 row)
Now he knows that he is pretty close to the right answer. When he guesses the right word, the previous query won't show how long is the path from the guessed word to right because they are the same. So, in this case, we would need to handle this in another way in the code that we are developing the game.
Conclusion
Apache AGE can be very helpful for games that need to store data that are related to each other and comparing them is a key feature. The extension allows us to easily write graph queries and with a lot more performance compared to other graph databases.
If you want to learn more about Apache AGE, here are some links to check out:
Top comments (1)
Amazing! This is a very cool game!