Text Adventure Time! (Runnable Commands)

Some time ago, when I was brushing off my Java, I wanted to get my hands dirty while making something fun. I LOVE text adventure RPGs, so that’s what I attempted to build.

This is the third post documenting my single user dungeon development adventure.

In our last Java Text Aventure post, we left off at commit 8fc5b7a, where we implemented an Enum class for command handling. Everyone agrees that that was some scary code, and I did something about it in the next commit.

Moving forward, I’ll be writing about groups of commits by feature rather than sequence. Updates to commands, for example, are spaced all through the commit history, and maybe I can do a better job of separating features in the post-mortem of these commits than I did while I was actually writing them.

Ahem. Anyway, in this post I’ll be covering the conversion of command processing from an Enum list to a HashMap of Runnables. Such names of things! So exciting!

Once that’s taken care of, I’ll be writing about a few other bits related to commands that got introduced later. I’ll be skipping over commits that affected other features, but we already talked about that.

Here is the list of posts published on this project so far!

Introducing: Runnables!

I said to a friend: Look at my code. This Enum thing is working, but it feels horrible. There has to be a better alternative to a switch case with Enums. Help!

And he said to me: I have no idea what you’re doing here. It is indeed horrible. Try using a map of Runnables instead!

And I said: Let me Google these ‘Runnables’.

And I did. And it was glorious.

A little while later, I had a working prototype!

The Runnable object can execute a method in a separate thread (or the current thread). Using a HashMap lets me select the desired method quickly, instead of having to use a switch or if/else chain.

Check out the repo for this post and follow along!


Target commit (should be the current commit):

Running the game:

Implementing the Runnables

There are three main pieces here:

  • Main.java
  • Commands.java
  • Input.java

When the program starts, a HashMap named commands is created.

Then in the main method, it gets populated (later this was converted to populate the map on creation). Here I’m adding the north command.

That’s a lambda!

Basically, the String “north” is mapped to the Runnable method Commands.goNorth(), which does pretty much what the NORTH case did in the Enum implementation: change the current room by 1 in the upward (negative) y direction.

In order to use the method as a Runnable, the signature needs to have a type Runnable. However, the return will never be used, so we just return null;. Of course, returning a null is bad practice, but if the compiler wants to give us a hard time, why should we play nice? Just kidding. The compiler is our friend. When the Runnable execution is complete, the thread will just die and nothing will get returned, so no need to panic.

Convert user input into a Runnable and run it

Back in Main.java, we invoke the Input.getCommand() method, which returns a String. If the commands map has a key matching the String, thingToRun gets stuffed with the Runnable code. This Runnable gets passed to a new Thread to be executed with the Thread.start() method.

And there you have it!

What are you waiting for? Get those pants. Pants are good.

Matthew Odle

Indie dev, autodidactic polyglot, lover of programming, dad, musician, writer, mentor

4 thoughts on “Text Adventure Time! (Runnable Commands)

Join the Discussion