Game Programming Blog

Zork – Navigation

We have quite a bit of functionality in our game now, but its hard to show it off without being able to move. In this lesson we will finally allow you to explore the world by navigating from one room to another. Along the way we will also update our systems so you can see the descriptions of the rooms and the entities that you find there.

Portal

A portal is like an exit pathway which takes a player from one room to another. It is the only new model we will need to complete this lesson.

When a valid portal action has been executed, it will call this method to determine what room, if any, to move the player to. Some portals will not actually have a valid room target because that direction is blocked. In the future we will show how triggers can unlock a portal.

This convenient method will look for a portal in the current room that matches the indicated direction. The provided direction can be a fully typed cardinal direction like “north” or “southwest” or an abbreviation such as “E” or “NW”. You can also travel “up” and “down” at some locations.

The portal’s direction field in the database actually stores a comma separated list. This is because the portals in Zork can be used by more than one direction. For example, from the starting room “West of House” you can travel “North” or “Northeast” to reach the “North of House” room. If you look at the map you can kind of see that the layout of the rooms is in a circle around the house, so either direction can sort of make sense.

Personally I found it a confusing design because I felt that anytime I travel in a particular direction I would expect the opposite direction to take me back to my previous location. When I go “North” to “North of House” I expect “South” to return me to “West of House” but that is not what you get. I initially played without a map and was immediately lost.

This method is invoked from the Portal system after activating a portal. It causes the player to be moved to a new location. It also prints a room title and description to the screen, unless you have already visited the room before and then it should only print the room title. Afterwards, it calls the “visit” method which updates the database to show that the room has now been visited.

This method allows you to move any entity with a presence component to the specified room id. Note that the room ID doesnt have to be valid, and is one way that you can hide entities that are not needed.

The “visit” method actually performs the update in the database to toggle the flag on the appropriate row. Behind the scenes this will end up being translated to an Integer value of 0 or 1, but we are able to work with a type with a clearer intent.

The “entitiesInRoom” method builds a list of all game entities that appear within the current room. Currently two different components could imply that an entity is located there: the presence and containable component. Therefore I make a single array which appends the results of “entitiesPresentInRoom” (for presence components) and “entitiesContainedByRoom” (for containable components).

Sight System

Since we are enabling the ability to travel the game world, it seems necessary that we also provide a way to look at it. Let’s open up the Sight System and extend it with some more methods:

The describe room method is invoked whenever we use the look command without a target. It prints the room title and description even if we had already visited the room before. In addition, it will list any entities that are considered “notable”.

Here I have provided a simple implementation for the ability to “examine” or “look at” an entity. Some of the special traits such as whether or not it is “open” will be listed, or if the entity is a container it can list the contents, otherwise it will print a generic response that there is no trait that matters.

Actions

We’ve got the necessary models and systems in place, so now we can add some actions which allow us to explore our world!

Portal Action

Like I have done before, the command which is actually registered for this is a subclass of the compound action. In this case the compound action only has a single action within it, which makes it feel a little less valuable. However, I could see the desire to expand on this, such as if I wanted to support some more keywords like “enter” or “exit”.

The base portal action, which works simply by specifying a direction or the abbreviation for a direction works pretty simply by converting any fully specified direction to its abbreviated form, and then using that with the portal system to find a matching portal. If there is a match, then we attempt to activate it, otherwise we use a generic messge indicating that you can’t go the way you requested.

Look Action

This action makes better use of the compound action base class. It supports the ability to look at a room (when specifying no target) or an entity (when specifying one target). It also supports a synonym for “look” by implementing “examine”.

Demo

We wont need any temporary code for our demo this time. Simply build and run and start trying out the new commands. Look at your room, or an entity in the room, or try to navigate around the world. You can visit almost every room in the database, although entering the house requires us to implement some special triggers.

Summary

This was a pretty simple, but important lesson. Most of what I presented was pretty standard, such as creating models to represent the tables in our database, or providing a system to work with that data. However, when you compile enough of this work together you end up with a very large and rewarding experience. By completing this lesson we are now able to explore our game world, and to a small degree we can already interact with some of it as well.

Don’t forget that this project is accompanied by a repository HERE. There will be one commit per lesson so you can see exactly how the project would have been cofigured and how the code would look at each step.