StupidRPG: Milestones

Now that coding is properly back underway, it’s time to layout some development milestones. It’s a big project and there’s a long way to go. This post will contain small spoilers, which will not be hidden with spoiler tags.

Phase I: The Black Box

Milestone 0: The Engine (Done)

This milestone was considered finished with the completion of the ECS, NLP, and Core module. The majority of development after this point consists of creating Modules, Components, Verbs, and Entities.

Milestone 1: The Forest (Done)

Laying out the starting area of the game with some basic gameplay (movement, NPC interaction, containers, etc) as a proof of concept.

Milestone 2: The People

Adding interactive NPCs in the starting region, complete with dialogue trees, awareness of the player and of each other.

Milestone 3: The Quest

Giving the player objectives, measuring their progress, and offering a gameplay path to the first act of the game.

Milestone 4: The End

This one might sound out of order, but immediately after the prologue I’m going to write and construct the ending of the game. At the end of this milestone, the game will be in a fully playable state with beginning and end, choices to make, and challenges to overcome. The rest is content, content, content.

Retrospective I

After completing milestone 4, I’m going to pause briefly and consider the rest of the game’s structure. This is effectively a second design phase to make sure I’m on the right track and that the plot/quest/world/style are working well.

Phase II: StupidRPG

Milestone 5: Act I

Content milestone. Two regions, one NPC, and a couple challenges.

Milestone 5: Act II

Content milestone. Two regions, several NPCs, and many challenges.

Milestone 5: Act III

Content milestone. Two or three regions, including a larger one. Many NPCs, many challenges, more social interactions. Leads into the endgame segment from Milestone 4.

Retrospective II

The second retrospective will assess the game as a whole, looking at:

  1. Content that should be cut (sometimes less is more)
  2. Areas where content needs added
  3. Areas where the content doesn’t work
  4. Fun factor

Milestone 6: Release Candidate

At this point the game should be feature-complete and content-complete, with all the changes from Retrospective II implemented. Top priorities are bug fixes, editing, and balancing.

Milestone 7: Release

The game is done(ish)!

Licensing & Copyright

Short post today. I’ve been thinking a bit about how to license SRPG. On the engine side, I’m learning toward a permissive open source license such as MIT, LGPL, or the more extreme WTFPL. It’s not much of a technological marvel, and probably doesn’t have much use outside of a very specific niche.

The actual content (story, locations, NPCs, etc) of the game will likely be covered under standard copyright rules. At this time the plan is to make the game freely available for play in an online format (though I’ve done a couple experiments with wrapping it inside a native app).

StupidRPG: Game Ticks

A game tick is a unit of time for something happening in the world. Generally, when the player takes an action, a tick occurs. Entities within the ECS can watch for ticks and take actions. NPCs, for example, have the opportunity to take an action on each tick. You can think of a tick as a round of combat in D&D, where each combatant has their own turn within the round (in a particular order).

Ticks are controlled very flexibly, allowing for layers of precedence and handlers:

  1. Global: defaults to on, run after any user input
  2. NLP: disables current tick if the player’s input wasn’t understood
  3. Verb: enables/disables current tick for an entire verb (e.g. INVENTORY)
  4. Callback: can enable/disable current tick on the fly during verb callback

Some fun things I might look into:

  • Time scaling as a result of plot or a character power (ticks happen more/less frequently than normal).
  • Exempting a creature from the normal tick rules, allowing them to act after bad input or non-tick verbs.

Weekly Update #4

Progress!

Changelog:

  • Fixed dialogue tree bug that was preventing other progress. Now the sword won’t talk to you while you’re trying to talk to Ranger Bob.
  • Finally solved a Rubik’s Cube without using a guide. Now I can go do more useful things with my life.

Known Issues:

  • Nothing new

Next Up:

  • Fill out Ranger Bob’s dialogue tree.
  • Add The Twins.
  • Litterbug quest.

Replay Value: Something New From Something Old

I’ve been thinking a bit about replay value in a text adventure. SRPG is, as the name would indicate, an RPG, so there’s some inherent replay value in the form of race/class choices, moral decisions, etc. Getting away from specifics, though, replay value is all about getting a new experience from a familiar construct.

Giving the player access to new/different mechanics is a good start. SRPG does that via race/class selection, which changes the starting items and stats for the player. If people feel invested enough to replay the game with each race or class, I’ll feel pretty satisfied about the variety available. But there’s probably more potential. Other avenues for replayability include: multiplayer, random events, procedural generation, and bullheaded dedication to completionism.

Procedural content is of particular interest to me, but in most games I’m familiar with, that amounts to a slightly different random experience. In some cases that’s perfectly acceptable. Minecraft is one of my favorite games, though its replay value is largely driven by the combination of ‘another slightly different cave’ and ‘slightly different player base.’ I have more ambitious goals for procedural content in SRPG, using NPC behaviors in games like Elder Scrolls as a template.

NPCs become interesting when they have their own lives, with motivations, goals, and challenges. Similarly, the same storyline gains new life when given a different cast or a new turn in the river. While I don’t aim for a completely new experience for the player each time they begin anew, I hope they’ll get a little bit more out of the game if they choose to replay it with fresh eyes and fresh decisions.

StupidRPG: Output Queue

Input queue, output queue, callback queue…SRPG has all kinds of queues. The output queue is a fun one. On the basic side, it handles the process of outputting text to the browser (paragraphs generated by the player’s action). It does a few more interesting things as well.

Timing

Why a queue? Why not just output all the text immediately. Two reasons: screen management and dramatic timing.

Screen Management

Being a browser game, the dimensions (width and height) of the window in which it’s played are not known to me at design time. In particular, I don’t know how many lines of text will fit on the screen vertically. The output queue lets me ‘pause’ the flow of text when room runs out, and prompt the user to press a key to continue. You might recognize this feature from the classic Infocom games.

Dramatic Timing

This one is more fun. Not all text has to be drawn to the screen at the same speed. Pauses can be inserted between text items at will. This is particularly useful when outputting narration or dialogue, in which moments of hesitation or consideration by the GM or NPCs will make the output feel more lifelike.

Effects

I haven’t made use of this concept yet, but the output queue also allows for the inclusion of special effects down the road. For example, a typewriter output effect, backspacing to erase a typo by the GM, and so forth. Something to look forward to for the next time I don’t have pressing bugs to deal with.

Wish List: Multiplayer

One of my many pie-in-the-sky goals for StupidRPG is networked multiplayer. I have absolutely no hands-on experience with network programming (browser or otherwise), so it’s toward the bottom of the priority list. I do know a little bit about websockets and a moderate amount about databases.

The engine for SRPG was built with future multiplayer in mind (sort of). Actions usually enter the queue from local input, but that’s not a requirement. I’ve already shown examples of input being added via test functions and via previous input (an action triggering another action). Handling a remotely-entered command (and appropriate context, such as the remote player entity) doesn’t pose an architectural problem. There are, however, many design challenges to overcome to make multiplayer work in a plot-driven, turn-based RPG. I’ll talk about a few problems and concepts I’ve been considering.

Problem: Whose Turn Is It?

In short, for the game to work as-is, it needs to remain purely turn based and synchronous. Players take turns inputting commands, then the engine distributes the commands to the other players. For common actions like moving around, opening doors, and picking up objects, this is no problem. There are a few cases where it gets tricky though:

  • Command interrupts (these need to be contextual per-player)
  • Dialogue trees (does P2 have to wait for P1 to finish an entire conversation before they can take an action?)
  • No-tick actions
  • Guided segments like the intro

I have solutions in mind for some of these. No-tick actions (which I’ll talk more about in another post) don’t need to be synchronized between players. This means P1 can look at their inventory while P2 is taking their turn, for example.

Thinking more broadly, I’ll need to develop a method for flagging synchronous/asynchronous sections (in addition to no-tick actions). Synchronous actions can only be done on your turn, while asynchronous actions can be done at any time.

Problem: Gameplay

This ties in to the previous problem a bit (particularly the handling of dialogue trees), but it’s a more fundamental set of questions. In short, what does Player 2 do? Are they another fully-fledged individual just like Player 1? Are they a sidekick of some type? Are they present for the duration of the game’s plot? Do I need to build separate puzzles and gameplay elements for the solo and multiplayer modes?

Concept: Act IV Multiplayer

Traditional multiplayer aside, another concept I’m considering is to only introduce multiplayer at the end of the game’s story. Essentially, the campaign would wrap up and then the game would turn into a more open world with multiple players. Might be overly ambitious, and for a new player who wants to play with a friend, they have a lot of content to get through first.

Concept: Asymmetric Multiplayer

Lastly, I’m looking at asymmetric play. Instead of having both players exist as equals in the storyline, the second would have a different experience entirely (sidekick, animal, etc). Some Wii U games use this type of play for the 5th player, allowing them to assist the other players from outside the regular mode. This is just as ambitious as the Act IV concept, as it needs a lot of extra content and coding to be meaningful.

StupidRPG: Save, Load, & Undo

Most text adventures (that I’ve played, at least) don’t feature the auto-save ‘checkpoints’ common in modern videogames. They do include SAVE and LOAD commands which work exactly as you’d expect, but they also typically provide another command for state management: UNDO.

In a singleplayer, turn-based game, UNDO is a pretty straightforward feature to implement. There are a few different approaches, but I’ve elected to leverage the savestate functionality for efficiency’s sake. More on that in a bit.

SAVE

The save command in SRPG is handled primarily by the ECS. Since Everything is an Entity, I can simply loop through all the entities, building a new object which can be stored in JSON format. From there, it can be saved in the browser’s local storage or downloaded to the user’s computer.

Not every piece of data on an object is needed for savestate. Most callbacks don’t change once they’re set, and many object attributes are static as well. Accordingly, each Component can specify the persistent attributes that should be included in the save process. For example, the Living component specifies that the HP attribute should be saved.

LOAD

Loading works exactly as you’d expect: saving in reverse. The JSON data is read back and the entity attributes are re-applied to the live versions.

UNDO

Undo is a combination of an internal save (before each action, save the current state) and load, allowing the player to jump back in time just as if they had manually saved and loaded. Effectively, it’s an automated Quick Save feature. Supporting additional steps of undo is possible, at the cost of additional memory and CPU time.

Because UNDO is a verb just like any other in the game, there are some interesting opportunities for integration into the mechanics and story. That’s a surprise for another day, though.

Next Steps

There are a few shortcomings of the current model:

  • Saving multiple levels of undo is not cost efficient. I need to do better profiling of the memory consumption of the game.
  • Much of the saved data is not actually changed from the base entity state. I could reduce the size of the save files by only saving attributes that have actually changed, but that means adding more tracking code.
  • Some circumstances need special handling. For example, what happens if the player uses UNDO directly after SAVE?
  • Entities have to be uniquely identified in order for loading to work properly. This isn’t currently a problem, but could become one in the future with dynamically generated entities.

Testing a Text Adventure

Testing is an important component of any software project, and games are no exception. Javascript is easy enough to unit test for core functionality, but the genre of SRPG offers an interesting opportunity for automated game-aware testing.

All input in the game is simply text, and the game engine already has an ‘input queue’ capable of handling multiple commands in sequence. This feature is already being used for one simple test process, to get me back to a particular state in the game after making changes. It can be taken further, however.

Random events in SRPG are handled with a seeded random number generator, meaning that given the same seed and same inputs, all random effects in the game will happen in the same way. That means I can save a transcript (sequence of inputs) and a seed, then play them back and check the output. This is a natural place to automate tests.

My current plan is to develop tests that specify:

  • Starting state (optional, used to shortcut to later portions of the game before testing something specific)
  • Random seed
  • Input sequence
  • Test callback

If/when the input sequence concludes, the callback is run to check for certain elements. For example, checking the last text output, or looking at an attribute of a particular object.

Helpful tests could include:

  • Intro process works (race/class selection)
  • Movement works (starting area)
  • Checking inventory works

During each build, I can run all the tests to get an idea of the health of the game code, and find out immediately if my most recent changes have broken anything.

StupidRPG: Tutorial or not Tutorial

One of the open questions I’m contemplating about the design of SRPG is the inclusion (and nature) of a tutorial. I want the game to be reasonably accessible to people unfamiliar with text adventure conventions, but I don’t want an obtrusive starting tutorial. I’m considering a three-part tutorial: implicit, explicit, and help.

Explicit Tutorial

In an explicit tutorial, the player knows they are being taught how to play. The tutorial gives instructions and advice, like:

Navigation in StupidRPG is performed using cardinal directions (like on a compass), along with context-specific movement like up and down. To proceed to the next area, type NORTH or N, then press enter.

While helpful, this information is not well-integrated into the game, and is only of interest to complete novices. More experienced players will likely want to skip the tutorial.

If I include an explicit tutorial, it will likely be opt-in (i.e. the player will be prompted to start the tutorial if desired).

Implicit Tutorial

An implicit tutorial is more appealing to me, as it’s fully integrated into the game (and story). If done well, the player might not even notice that they’re being guided through the early portions of the game. The first level in Super Mario Bros provides a great example of an implicit tutorial.

While I can’t (probably) teach the player something as basic as how to enter a command via implicit means, I can definitely guide them into certain actions that give greater insight into the game mechanics. For example, in the first area of the game, an item on the ground is described to the player. Loot hoarders that they are, most players will attempt to acquire it (via TAKE OBJECT, PICK UP OBJECT, etc). The first area also has only one exit, forcing the player to learn a basic movement command to progress.

I haven’t discussed Command Tags much previously. Command tags take advantage of the game’s HTML output by creating clickable, highlighted links in the game’s text. This is mostly intended as a utility, allowing the player to simply click on objects, people, and scenery to interact with them rather than typing out a command. The default action for command tags is LOOK AT (OBJECT). When a command tag is clicked, the associated input (which is always a text command that they player could have typed themselves) is echoed back and executed. That is, the player sees the command that was executed. If they’re paying attention, they just learned how to use the LOOK command.

Help

Lastly, I plan on including a help menu (accessible via a link or by typing HELP). The menu will include a general overview of interacting with the game, as well as specific instructions for core commands (MOVE, LOOK, TAKE, INVENTORY, etc). A hint guide might be a nice future addition as well.

Putting it All Together

There are opportunities for combining these instructional elements. For example, if the very first command the player enters is not understood, they can be prompted to take the tutorial or view the help menu.

Right now I’m focused on the implicit tutorial (which I believe is the most valuable), followed by the help menu (which acts as a nice reference even for experienced players). The explicit tutorial is unlikely to get time devoted to it until later in playtesting.