I’m a child of the ’80s. While I can look back now and recognize how naive, weird and downright cheesy much of the decade was, I still feel a strong sense of nostalgia when I think of certain things from my childhood. One pop culture phenomenon I fondly look back on is the Choose Your Own Adventure series of books.
Ten-year-old me couldn’t get enough of them: I read every single one in my school’s library, borrowed them from my friends and annoyed my parents until they bought me some of my own.
A very thoughtful friend gave me an original set of three mint condition Choose Your Own Adventure books for my most recent birthday. I devoured them pretty quickly and – looking at them from my adult point of view – I recognized something new right away: These stories form a graph.
In fact, I started to wonder how the authors mapped them out and kept track of everything during the creative process. Obviously graph databases didn’t exist back then (we’re talking 1984 here, they didn’t even have Excel), but if it had been me, I’d have gotten a huge piece of paper and drawn it out as what we now call a graph model.
Then I watched Bandersnatch (Netflix’s interesting “choose your own adventure” interactive show about a “choose our own adventure” game), and saw that’s pretty much what the main character did. That guy could really have used a graph database!
I decided to have a bit of fun, and load up one of my Choose Your Own Adventure books into Neo4j Desktop so I could see how graphy it really was. I selected Choose Your Own Adventure #31, Vampire Express by Tony Koltz, ©1984 by Metabooks, Inc. and Ganesh, Inc.
It only took about an hour or so to create a graph representing all the possible paths in Vampire Express. I used a very simple data model, with
Pages
represented as nodes and each Page
node linked to the next by NEXT_PAGE
relationships. Some pages in the book simply point you directly to the next page in the story, and others present you with two or more options.
Where there are more than one options for the next page I created multiple
NEXT_PAGE
relationships from that Page
node, and put the text for the choices into “option” properties on the relationships. I also gave the first page an additional
Start
label, and each ending page an additional End
label, so we know where the story begins and ends. The “metagraph” or “data model” for this graph looks like this:
Using this simple model I was able to map out all the pages, choices and endings in Vampire Express. The full graph for the book looks like this:
Vampire Express as a graph, with the
Start
in green and possible End
results in red.Pretty neat, right? Ten-year-old me would have loved this graph stuff (especially if there was a driver for BASIC).
Using my graph and a few Cypher queries, I can answer some useful questions about this particular Choose Your Own Adventure:
Q: Are there any “loops” in the story that take you in a circle back to where you started?
In Cypher:
MATCH path = (s:Start)-[:NEXT_PAGE*1..]->(s) RETURN path
A: No, there are no circular paths in this adventure.
Q: Are there any pages not reachable from the first page?
In Cypher:
MATCH (p:Page), (s:Start) WHERE NOT (s)-[:NEXT_PAGE*1..]->(p) AND p <> s RETURN p
A: No, every page can be reached via a path from the first page.
Q: What is the shortest path to an
End
page from the first page?In Cypher:
MATCH path = (s:Start)-[:NEXT_PAGE*1..]->(e:End) WITH collect(path) as paths, collect(length(path)) as lengths UNWIND paths as p WITH p WHERE length(p) = apoc.coll.min(lengths) RETURN p
A: The endings on page 46, 87 and 107 can all be reached in seven “hops” (or page turns) from the first page.
Q: What is the longest path to an
End
result page from the first page?In Cypher:
MATCH path = (s:Start)-[:NEXT_PAGE*1..]->(e:End) WITH collect(path) as paths, collect(length(path)) as lengths UNWIND paths as p WITH p WHERE length(p) = apoc.coll.max(lengths) RETURN p
A: There is a path from the
Start
to the End
results on page 25 and page 59, each of which is 21 hops long, making them the longest story paths in the book.If I loaded a bit more data, I could ask even more questions of our graph. If I flagged our
End
nodes as being either “good” or “bad” endings I could see what the shortest path would be to a specific type of ending. I could put word counts for each page into the graph and choose the shortest story path not just as a count of hops (or page turns), but in terms of the time it would take to read (since fewer words would mean a shorter read time).
If I loaded all the text for the book into the database, I could see how many different paths mention Count Zoltan or the Gypsies. As an author of Choose Your Own Adventure books, being able to easily track and visualize this kind of information about my work would probably be very useful.
Conclusion
Pathfinding use cases are a great fit for Neo4j, and hopefully this brief example has given you some ideas on how Neo4j can be used in different pathfinding scenarios. If you’re not already using Neo4j, you can download the Desktop Edition, or launch an online sandbox. Happy graphing!
[I think it’s great that Choose Your Own Adventure books are still a thing, and I still love them. I think they work better for children, though, so if you’re looking for something similar but more challenging check out the Fabled Lands series of books. They’re like Choose Your Own Adventure books crossed with a pen-and-paper RPG, including character sheets and dice rolls, but without the need for a Game Master. They’re really good fun and I highly recommend them – and they’d make a really fascinating and very complex graph! Van Ryder Games also make a really interesting series of “choose your own adventure” graphic novels which you might want to try!]
Take the Class