Tales of the Rampant Coyote

Adventures in Indie Gaming!

Frayed Knights 2: How to Save the World (State)

Posted by Rampant Coyote on July 5, 2013

For today’s Frayed Knights discussion, I’m actually going to get a little general, and talk about a topic common to virtually all modern computer and console role-playing games: saving the world! Or, rather, saving the state of the world, and dealing with persistent data. It’s pretty basic stuff, and I’m not going to delve too deeply into technical issues. But it may be of use to less-experienced game developers (whether programmers or not), or just the idly curious as to what kinds of effort needs to go into making a computer RPG.  As always, be sure and check out Frayed Knights: The Skull of S’makh Daon on this website and give it a try. The free demo includes the first dungeon, and is a nice little self-contained adventure.

One of the aspects of the oldest of the old-school CRPGs that I don’t really miss all that much is how little of the game state was saved. Aside from your own character or party, much of the content was either random, or was reset every time you re-entered the dungeon. This meant that players couldn’t really leave their “mark” on the world, limiting interaction. And while it could be either a good thing or bad thing depending upon perspective, but it certainly encouraged grinding in “easy” spots.

Nowadays, much of the world information is persistent – carrying over between visits to areas, and between game sessions. Where it isn’t, it’s more often a design decision rather than a technological limitation. While Borderlands has many trappings of an RPG, areas are intended to be revisited, and boss monsters taken down multiple times, especially in multiplayer. The persistence is still there, in the form of quest status and a deliberate delay before monsters and treasures respawn. This is as intended, and it is a design decision borrowed from MMOs (which Borderlands also shares a few attributes with).

Ultima_7SI_pt2The first game I remember playing which had really impressive saved world states was Ultima VII. I’m pretty sure that’s one of the reasons why it remains one of my all-time favorite games. Ultima VI was the same way, but I’d kinda skipped that one and went back to it later (and to this day, still haven’t played it to completion…).  Even it had its problems at first, little bugs like having keys disappear from your inventory and ruining the game. Kind of a big deal.

While this is a feature of most modern RPGs today, few games have the level of interactivity requiring the level of world-state data as those Ultimas from 20+ years ago. I think this may be a reason why I’m so fond of the recent Fallout and Elder Scrolls games – even with respawning, they have some really impressive persistent world state information. And then there’s Minecraft

So how do you keep track of all this information, and save it out with the saved game? While the exact nature of the system may change from game to game (Minecraft has different needs from Dragon Age), here’s the approach I’ve used for Frayed Knights. While I’ll talk a little about implementation details,  for the most part I’m going to keep this kind of general so that non-programmers can follow along.

Naturally, with the editing tools and everything, my game world has an initial state. This is part of the initial game data. By default, this is how everything in the world is supposed to be, when the game starts. All of the quest flags are set to “false” or zero, all game state variables are at zero, all the doors are closed, all the traps untriggered, all the chests unopened, all the events un-triggered, no additional bags or other objects lying around anywhere, none of the items in the world disturbed from their original resting place. This is the world in its pristine state.

This is the easiest save game state possible – this is how the world will come up if there’s no save game information whatsoever (other than character information, which is a whole ‘nother story).

FK1IntroOf course, almost immediately, the player starts changing the world. In Frayed Knights: The Skull of S’makh-Daon, this is literally the first moment the actual gameplay begins – the party starts off a dialog. I don’t want the dialog to play every time the party enters the dungeon (either from outside, or by loading the game), so I have to flag this event so that it knows it can only play once, and that it has already happened, so it will never happen again. This will have to be part of the persistent data that gets saved out with every game. If the player saves the game immediately at this point, without having even moved, there’s one piece of save-game information already that has to be recorded.

At this point, the experienced game developers are probably thinking to themselves, “Duh, that’s obvious!” while some non-dev-types might thinking, “Huh. I never thought about that. That sounds like a pain in the butt.” Both apply. A persistent-world RPG (IMO, a description that should be redundant) should be built around a framework that makes this part not such a pain in in the butt from the get-go. It’s just one of many things that need to function behind the scenes to make a modern-featured RPG work.

Okay, so what I do is save out all of these changes (called “deltas”) from the pristine world-start state. Every piece of data that is part of the persistent world information has to come from (or go to) this “world state” object. Everything. It’s like the gasoline to your engine.  Every object in the world queries this world-state object to find out about itself. A chest will see if there’s an entry in there for itself and uses that state information if it exists – otherwise, it simply defaults to its starting state.

As you can naturally deduce, this object gets a lot bigger as the game progresses. It has to be relatively fast, too – when it gets queried for state information, it can’t spend a lot of time searching. So for programmers – this probably means that for a big game, a single, massive array that gets linearly traversed is probably a bad idea. For Frayed Knights 1, using TorqueScript, I ended up creating a binary search tree, and every type of state data had to be able to save and load itself.  In more modern, fully-featured languages (like I am using now), I can take advantage of serialized object data and dictionaries (a key/value collection object that has a pretty fast lookup). I know of people – especially working with MMOs – who just handle everything directly via a SQL database. That can work too. The implementation details really depend on what you are doing.

Anyway – back to the story. This sort of structure necessitates that every object with persistent state information must be uniquely identified somehow. For example, keeping track of which doors are opened and closed in a level – each door has to have a unique tag so it can query the World State object by saying, “Hey, I’m Door #15 in the Hobgoblin Bunker. What’s my state?” If the identifier is not unique, then Bad Things Happen, as two doors overwrite each other’s information. This is how you get nasty things happening like the save game ending up being in some kind of unwinnable state because of a bug. This is what is likely to happen if you depend on manually assigning the unique ID, and you often depend on copying and pasting objects to speed development.

(And yes, I speak of this from the vantage point of painful experience…)

Likewise, the unique identifier needs to be something that will survive modification. Basing the ID on the X,Y,Z location in space will give you a pretty unique identifier for the time being, but what happens if you find you need to nudge the location a quarter-meter to resolve some pathing issues after the game is released? OOOPS! Everybody’s game state from that point on – if they’ve already interacted with the object – is going to be broken, as the unique identifier will have changed when you moved it.

For Frayed Knights 2: The Khan of Wrath, I’ve hopefully learned my lesson here, and I’ve made some automated tools solve most of these problems for me. They are simple and ugly, but they do the job.

There are other optimizations to take advantage of, as well. For example, there are some global pieces of state information that need to be recognized anywhere and at any time. For example, quest states and some event information. In Frayed Knights, I also like to record how the party resolved certain situations, so I can use it against the player later. Er, I mean, have the game react believably according to the player’s previous actions.  This meant writing many variants to certain dialogs, but I thought it was more fun to have the dialogs refer to specific actions rather than be generic enough to cover all the possibilities (though at times I did that too).

But there are other kinds of state data that only apply to a particular scene when it is active. For example, if you are in the Hobgoblin Bunker, there’s no reason to care about what enemy patrols are active in the dungeons below the Tower of Almost Certain Death. That’s a possible optimization to make searching for information a little faster, but for many games that might be an overkill. Including my own. It’s just a suggestion.

Anyway – this isn’t exactly rocket science, nor is it particularly sexy. But it’s one of those things that developers have to deal with when making an RPG. It’s one reason why RPGs have a (deserved) reputation for being hard to make (compared to something like the ubiquitous indie puzzle-platform game). There are some toolkits out there which solve many of these problems for you, but it’s not a particularly challenging problem if handled correctly even if being developed at a lower level.


Filed Under: Frayed Knights - Comments: 3 Comments to Read



  • Chad said,

    On my first game Legends Arcana I saved all data in a text file the only thing I stored was character, quest, and location data. All the dungeons reset when you reentered with the exception of any creature or event trigger with a quest marker.

    On Tales of Illyria I serialize Java Objects to disk. I save and recall much more data in just a couple lines of code. Again I crafted the game in such a way that I only need to save party,quest and location data. I store all the miscellaneous flags & objects in a Hashtable.

    Text files have the advantage and disadvantage that they can be edited by hand. They are also a bit more portable between different versions of games. But it takes much more code to manage them.

    Serializing objects is easy but you can break your saved games if you change your objects in certain ways so you have to be careful. They also aren’t as easy to import into a sequel as you would have to keep that legacy object structure in your newer code. Is there away around this?

    Chad

  • Felix said,

    Chad, in the way of data serialization I’ve only worked with JSON a little, but support for the format usually includes custom object encoding and decoding. So you can import data exported by some other application entirely and control exactly what classes it maps to in your code, filling in any missing pieces as needed. Would that help?

  • Chad said,

    Hi Felix,

    Yes you are correct I’m currently using native Java serialization. Its Android so for some reason it doesn’t support XML serialization. JSON is a great way to serialize data. If you use something like GSON from Google. It can automatically convert your JSON into Java and vice-versa.

    Its not going to be an issue for me this time as I don’t plan on allowing imported games into the Sequel as it has an entirely new cast of characters.

    Thanks,
    Chad

top