Welcome to Raph Koster's personal website: MMOs, gaming, writing, art, music, books.
Game talk

UO’s resource system, part 3

June 5th, 2006

I’ve now written two posts that were far lengthier than I anticipated, about the way that UO’s resource system was originally intended to work. The first dealt with underlying data structures, and the second with applications of those data structures to the actual world. I want to talk a bit about future directions that we didn’t get to pursue.

Cool ways to use what we already had

The mining system in UO was an example of “transmutation” in action. We placed ORE in the chunk eggs based on the presence of rocks and the terrain rock texture. We mined ORE out by clicking on rocks or the rock texture and transferring the ORE to the new “pile of ore” object.

When I added in the varieties of metals to the system, the way I did it was by adding a dynamic variable to the chunk egg. The were called “object variables” or “objvars” in UO parlance, and they were essentially flags with values that could be attached to any dynamic object. You could tag someone as “BEAT_THE_HARPY” with a value of “TRUE” and then use hasObjVar(target, “BEAT_THE_HARPY”) to see if the objvar was present, or val = getObjVar(target, “BEAT_THE_HARPY”) to get that value into a variable for script use. These objvars were persistent, so you could build complex systems out of them.

I simply attached a little script to every chunk egg that checked to see if it had an objvar that defined a metal type. If it didn’t, then it randomly chose a metal type and set the objvar to that value. This meant that after this script was updated, every chunk in the world bore a different kind of ore. I weighted some to be rare and others to be more common.

When the ORE was mined, I had the mining script transfer that variable to the new object along with the ORE resource. I also had it tint the ore graphic based on a standard lookup table, dependent on what the value of the objvar was. And thus colored armor was born — we simply had each step transfer the variable along.

This worked even when we actually recycled the ORE and conjured up METAL out of thin air instead. This was the step of refining the ore into ingots. You could also combine ore — I don’t recall how we handled this, but it was probably by picking the commoner of the two types. It would have been fairly easy to add new metal types that were not minable but were only available as alloys, too. In a more modern system, we would have instead had types of METAL such as IRON or COPPER that inherited from the base type — and that is in fact how SWG worked.

This sort of transmutation, where you query the amount of RESOURCE1, delete it, and then create a corresponding amount of RESOURCE2, permitted the concept of “refinement” of one type of quality into another. COTTON or FLAX into CLOTH is a similar thing, only with the wrinkle that it permits two different initial sources to become the same sort of thing in the end.

I mention this example just to point out that there were a lot of possibilities for the use of transmutation of one resource type to another; for example, a stone mage could use up ORE as resources and turn it into MAGIC; really, we should have made one’s mana pool be literally how much MAGIC resource they represented. A druid could have instead drawn power from the amount of GRASS or TREE that was around. And a necromancer — well, every time something died, it could have added DEATH to the chunk egg based on what was killed; a necromancer would then be able to “mine death magic” from spots where many things had been killed. Had we done this, I am sure we quickly would have had necromatic sacrifice altars, and they would have intentionally herded players (who of course would carry much power!) to those places to die. Temple of Doom, here we come…

Other applications based solely on what was already present:

  • You could do real tracking, based on things leaving traces in the chunk eggs.

  • You could have NPCs or creatures who collected or desired items with specific resources.
  • You could easily do a nice “detect magic” or really, “detect anything” sort of informational spell, with strength of the glows dependent on the amount of the resource present
  • You could create secret or transmutation paths — mix MAGIC and METAL to make MITHRIL or something, regardless of what the item looked like originally.
  • You could do “melting down” of materials.
  • You could create greater or lesser susceptibility to damage based on conditions. It’s easy to imagine a HUMIDITY value stored on a chunk egg — it could even move around. And then it could affect the growth rate of GRASS or the decay rate of METAL.
  • This also reflects the whole “dragon fire breath actually sets things on fire” thing.
  • Player actions could affect resources on them, such as reputations with certain groups, karma, and so on. They could acquire the “scent” of things they worked with often, for example. This would then replace a typical stats system, which would need to be hardcoded to interact with every other data type in the game.
  • This could, for example, allow a disease to be transmitted invisibly across the game, affecting only, say, magical reagents — and players could be the carriers without knowing it, unless it was detected by a spell or skill.
  • Most obviously, had we chosen to incur the cost of streaming the chunk eggs, we could have actually made the rendering of the chunks change based on what the chunk egg represented. As the grass is eaten, bare dirt is left behind. As the ore-bearing rock is reduced, change the rock tile to gravel. As the temperature changes, draw dead grass or even snow. And so on.

I could go on; suffice to say that even with just an abstract property system and no real AI work, there’s lots of potential for a lot of interesting and fresh gameplay.

What we didn’t have: causality

But the real issue with something like the dragon example is, “how do I know that the dragon is hungry, and not just a random spawn?” In other words, there needs to be a sense of purpose to what is going on.

The reason why it matters that the dragon is hungry and not just a random spawn is because it suggests multiple ways to solve the problem. You could kill the dragon. You could also feed it to get it to go away. Herd deer in between you and the village, let’s say. The problem is, maybe there is no reason. How can the player tell?

Let’s take the simpler case of some rabbits who eat the lettuce out of a farmer’s garden. What you really want is for the farmer to tell you “I’s gots me some rabbit issues; filthy buggers’re eatin’ muh lettuce! I’ll pay ye ta ‘sterminate’em!”

The proposed but never implemented method for handling this required knowledge at one step remove. The farmer would DESIRE his lettuce; this means he would walk around where it was, when he was not hungry, and if he could pick it up, he’d transfer it to his home. But the rabbits want to EAT the lettuce. If the farmer knew the name and template type of whatever was making him unhappy by competing for his desired resource, then he could complain about it. And if we tracked what the player killed, he’d know that they were good rabbit exterminators and possibly provide a reward, without there being a static quest defined.

What’s more, if players killed all the rabbits, but what came along next time as a spawn that ate lettuce happened to be deer, or even a lettuce blight, then the farmer would respond in the same way — anything that was eating “his” lettuce would be somethng he could complain about, and reward those who took action.

Similarly, in the village-attacked-by-dragon case, the villagers would have to like having other villagers around, so they could complain that “their” villagers were being destroyed by something else. You could extend this to any number of things. Let’s say that the smith loves “his” METAL objects. If a rust monster wandered through town and damaged the METAL, then he would complain about that but no other villagers would unless they also DESIRED METAL.

The implementation problems here are tricky. First, we would have needed to have some sort of registry so that the farmer could know about the rabbits, who are a third party to his relationship with his beloved vegetables. Worse, we would have also needed to relay the player actions against this third party so that the farmer could supply rewards and commentary.

Because of these hurdles, and because there was always something more urgent going on, we never got this in.

A similar thing that we wanted above and beyond the basic resource system was the concept of targeted desires. Instead of abstractly liking all METAL or all MEAT, we wanted to support the ability for something to pick a favorite: a preferred sword, a favorite pet. The test case that we designed for this was actually a love triangle.

Both Fred and Bob would DESIRE (to be crude) HUMANFEMALE. They would both search around for an object that met their desire, which would mean they would both hang around a female human NPC whenever they weren’t hungry. However, if they found one that satisfied their desire (probably with a bit of a random roll) they would fixate on only that NPC, and poor Nellie would find that both Bob and Fred hung around her a lot.

Now, HUMANFEMALE is a consumable resource. Bob, when around Nellie, is actually reducing it. And that means, when you talk to Fred, he would be able to say “”I’s gots me some Bob issues; filthy buggers’re eatin’ muh Nellie! I’ll pay ye ta ‘sterminate’im!” (or something of the sort). Bob would be able to say the same thing in reverse. You could even solve the problem by finding something else for one of the two swains to do. Even more interesting — if the dragon came along and ate Nellie, both Bob and Fred would be the first in line to seek revenge, or give a reward to a player who tackled the dragon problem.

Similarly, rather than manually setting up paths and schedules for NPCs, you could create a script that has them gradually increase a FATIGUE value, or that switched their SHELTER from WORK to HOME locations based on the time of day. You could have law-abiding citizens have an aversion to anything that produced DARK, so that at night they would cluster in lit interiors and under lamps, whereas only thief NPCs would be in the shadows.

The highest level of interface to all of this that we would have wanted for players would have included the notion of town criers and other news sources that pick “stories” from the ether and broadcast them. “Farmer Hayseed is pissed off about his lettuce getting eaten!” “Plague of street urchins won’t leave noble warriors alone!” “Fred kills Bob in jealous rage over Nellie!” and so on.

Problems: closed loops, homeostasis, feedback

All of these sorts of applications rely on a large bank of dynamically assembled text that is contextual to the situation. With the current desire for international localization of text, it’s unlikely that you can even execute on this. Localization tends to demand static text, and indeed, UO had piles of dynamically assembled text that was removed when the title was localized to other languages, costing the game’s dialogue much of its flavor.

All of these higher-level applications can only really be built on top of a fully functional animal-level behavior system. What’s more, in work since then, I have become persuaded that in fact, you need to drive the simulation to lower levels, such as humidity and temperature, just so you don’t find yourself creating special cases for simple behaviors. This leads to the concept that you could in fact build the whole world out of this, and just render textures and objects based on what resources are present, a concept first demonstrated in ALife examples such as Sugarscape.

In fact, it should now be evident that what this represents, in totality, is just a fairly elaborate “artificial life” engine, grown to the point where it encompasses spawning, basic behaviors, and even a higher-order quest system.

However, without the following ingredients, there’s little point to implementing something like this:

  • It has to be visible and responsive to players. This includes exposing causality. Otherwise, it might as well be random.

  • NPCs need to be able to communicate to players about wants, and need to react to those wants.
  • Static data must be avoided at all costs, which is incredibly difficult for a traditional game development team.
  • The myriad of variables must push towards homeostasis, rather than boom-bust cycles. A lot of Alife sims end up in boom-bust, and that’s not interesting to users.
  • Naturally renewing resources can’t be in a closed loop, because of player hoarding effects.
  • You have to solve CPU issues with pathfinding and searches in order to make the system tenable.

There were discussions on MUD-Dev circa 1998 about other means to handle this sort of system within a reasonable CPU budget. One approach that would probably work for the latter is to use “level of detail” for the areas. If no players are around, stop instancing up individual wolves hunting individual rabbits; instead, save all those off, and calculate periodically how many wolves and how many rabbits would be there after a certain amount of time.

You could stuff the world data into a quadtree and run higher and higher-level sims, instancing all the data back out only when you needed to interact with it in granular fashion; or you could timestamp the last interaction, and “catch the sim up” when a player approaches. This latter method was in fact used for handling harvesters and the like in SWG, since they tended to reside in areas that we actually took offline when no players were around. Using hillclimbing and broadcasting rather than constant radial searches is another approach. Lastly, truly treating the whole thing as an artificial life landscape would allow you to even use image processing techniques to update the grid, since they have been highly optimized.

On the closed loops, I have come to believe they were basically a mistake. The real world offers resources that are infinite in practice for most situations; it is local scarcity that is interesting. The issues with exposing the causality of things can be solved, I am sure, but they will take some work.

In conclusion

To my mind, this sort of algorithmic approach to developing a virtual world is not only the past, in UO’s case, but also the future. It is not hard to imagine our crude “METAL” with no parameters acquiring things like “melting point” and “brittleness” and then being plugged into physics simulations in the holodeck. There comes a point where a robust simulation model, even an abstracted one, is a cheaper thing to develop than the giant piles of use-once quests and data that we currently enjoy in the MMORPGs today. Even social worlds would benefit from having this sort of underlying mechanic, because if implemented properly, it exposes simplified levels of robust interaction to everyone and gives people something to talk about.

I also think that there is nothing wrong with having traditional static data layered atop this. Making an NPC with a hardcoded quest, no FOOD, SHELTER or DESIRE needs, and blissful ignorance of the situation around him is still easy in a system of this sort. On the other hand, how much better if he knows enough to freak out when the dragon comes up to the castle and starts frying chamberlains.

I’d much rather be burning CPU on this sort of thing, frankly, than on 3d collision. A lot of players complain about whether or not they can jump over a short wall, and believe me, I feel their pain (a story for another day) — but the kinds of immersive power that a simulation like this can bring opens a lot more doors.

In the long run, I believe that all the pressures are towards simulationist environments, rather than handcrafted ones. CPU power continues to outpace the cost of human capability to design static scenarios. At some point, reality will catch up to our designs from 1995.

Postscript for the curious — I was reminded in the comment threads that the original UO strategy guide actually had in it all the resource values for everything in the game, as well as things like the actual AI algorithm for falling through FOOD, SHELTER, and DESIRE.

*

You can follow any responses to this entry through the RSS 2.0 feed. Responses are currently closed, but you can trackback from your own site.

Meta

Recent Comments

Categories

Tags

Recent Trackbacks

Archives



A Theory of Fun
for Game Design

Book cover for A Theory of Fun for Game Design, by Raph Koster

Press
Excerpts

Buy from Amazon

Twitter @raphkoster



The whole Web

Raph's Website

See popular posts »



After the Flood

After the Flood CD Cover

Available as MP3 download
$14.99


More stuff to buy

Gratuitous Penguin Wall Calendar

Gratuitous Penguin
Wall Calendar

$16.99


LegendMUD

click here to visit the Legend website

"The world the way they thought it was..."