I wanted to get my hands dirty while making something fun. I LOVE text adventure RPGs, and I LOVE MUDs, so I’m attempting to build a cross between the two: a Single User Dungeon (SUD).
A few notes on code quality
Most of this code is pretty rough. I was mostly trying things until they worked and reflecting on what went well and what didn’t. I do love that git captures this process for me. It’s like a time machine. I can go back and look at how awkward it was in the beginning.
I started with the skeleton code provided by this fellow. The zip can be found here. I know there are probably better ways to implement some of what he’s done here, but that’s not my focus right now.
You can fork my changes to the code here: hello-world-sud.
Or checkout the branch:
|
|
You can compile and run the program from the command line with these commands:
|
|
If everything worked, you should see this:
|
|
WARNING: Proceed with caution: that there creature is a mammal of action.
Initial Changes
First I added the Item class, so I could have an inventory as a list of objects rather than a list of strings. Then I duplicated that to make an Equipment
object, so that I could handle equipping those items. THEN I realized I should probably use inheritance, and set up a GameObject
class.
Converting from a list of strings to a list of objects was more of a challenge than it should have been, but with enough brandy, anything is challenging!
Program Flow
The basic flow of the program is this:
- Build the world (including populating rooms with items and monsters)
- In a loop: get and process the player’s command
Building the World
The main method in Main.java
sets the world up by calling the World.build
method.
Getting the Player’s Input
The program then waits at the Input.getInput
method for the player to enter a command, then returns that as a string.
|
|
Processing the Player’s Command
This part is a little embarrassing. What a long messy chain of if-else
. I promise I found a better solution later on. The substringing to determine the target of commands such as check
, attack
, equip
is also very poorly written. It’s not very clear what the string indexing is doing, and it’s easy to make mistakes when adding new commands.
Bonus points if you can find the potty humor (and more bonus points if you are as inspired as I was by the epic gem don’t shit your pants).
Simple status command
commit f8f03f768f
|
|
Changing rooms
The code for the directionals is not very DRY, and there are unclear variables of x
and y
, which basically are coordinates on a grid which identify a room. Choosing south here causes the current location on the grid to increment by 1
in the y
direction.
commit f8f03f768f
|
|
Setting up the Item and Equipment Objects
|
|
|
|
There were a few issues.
The primary issue was that anything could be equipped. Like toilet paper. While I found this vastly amusing, it didn’t make much sense from a practical standpoint, so I needed a way to restrict whether an item could be equipped.
The other issue was that my previously attempted equip code was overwriting the item in the target equipment slot when equipping a new item, which doesn’t make sense, and would be pretty annoying to a player. The player should be able to take it off and sell it for hard cashey-money. So I implemented a check for the map. If the slot exists in the map, find the item and remove it. Then equip the next item.
Basically, the Equipment.equipItem
method performs a series of checks and acts accordingly. Does the item exist in the inventory? Is it already equipped? Is there already something equipped to that slot?
NOTE: There is far too much going on in the Equipment.equipItem
method, and the logic is not as clear as it should be, but I fixed that later on.
|
|
Defining the Character Object
|
|
I was considering how to add loot to monsters, and how to separate monsters from NPCs, so I added a base class with properties for inventory, equipment, etc., then inherited the class with the Player
and NonPlayer
classes.
Combat! (Sort of)
|
|
Here we have rudimentary combat with half-baked math: monsterHealth = monsterHealth - playerAttack
. Still very clunky. The command is basically just attack thing
. The thing hits the player first, the player hits the thing, unconsciousness checks are performed, experience is rewarded where due. Very repetitive, no shortcuts, no loot drops, no forced combat (creature would ignore you if you don’t attack again). Patience, these will happen with time.
Player Unconsciousness Check
|
|
That’s Probably Enough
There you have it. A really basic, needs-work implementation of a single user dungeon (SUD) game (I’m not sure people call them that, but I like the way it sounds, and this is more MUD-like than text adventure, but without the ‘Multi’).