Introduction

If you venture north of the art gallery in Zork I, you'll find a paper attached to the wall:

>EXAMINE PAPER

CONGRATULATIONS!
YOU ARE THE PRIVILEGED OWNER OF A
GENUINE ZORK GREAT UNDERGROUND EMPIRE
(PART I), A SELF CONTAINED AND SELF
MAINTAINING UNIVERSE. IF USED AND
MAINTAINED IN ACCORDANCE WITH NORMAL
OPERATING PRACTICES FOR SMALL UNIVERSES,
ZORK WILL PROVIDE MANY MONTHS OF
TROUBLE-FREE OPERATION. PLEASE CHECK
WITH YOUR DEALER FOR PART II AND OTHER
ALTERNATE UNIVERSES.

I quite liked the idea of a self-contained and self-maintaining universe, as well as alternate universes, and thought I might try to create one.

This project is a kind of single-player MUD, or maybe "open world" "interactive fiction". I don't know if the idea makes any sense at all. I've had some great experiences playing MUDs, roguelikes, and interactive fiction over the years, and this is an attempt to capture and expand on some of that. Perhaps in a form that I might work on for the rest of my life, my own personal Dwarf Fortress.

In this "book," I'm going to try to formally structure my ideas a bit in a more narrative form than GitHub Projects, issues, epics, etc allow. I expect this project to take quite a while, assuming I live to complete it, so I figure it's worth getting things down on paper (so to speak).

"Hello, Sailor!"

On the shores of the Flathead Ocean, you'll eventually encounter a strange apparition:

Zork III

I remember, as a kid, restoring at this point dozens of times. I yelled all manner of things. I followed his ship (as the description would indicate, it's gone by the time you enter the next room). I tried everything but the actual solution, which is to yell "Hello, Sailor!".

The resolution to that joke was a long time coming, but I missed it completely, even though I was playing the three Zork games, switching between them whenever I got stuck with one.

Anyway, my overachievement at object permanence and underachievement at everything else is not the point. The point is that this melancholy and lost grandeur did affect me, as silly as Zork is. Flood Control Dam #3 has a similar effect. I feel some degree of horror at the plight of the adventurer in the twisty passages maze; perhaps we're to assume that he never managed to find his way out... but the curse of the rusty knife is a compelling alternative explanation.

And who was it that kept shutting and barring the damned trapdoor, anyway?

The Dungeon Master, supposedly, but I don't really like that answer. It feels a little intrusive, a little too neat. Was the Dungeon Master a thing in Zork I? It feels... plotted.

Now, interactive fiction is just that – plotted, authored. And it probably works best like that, with the flexibility high but the editorial process working to trim the fat and ensure a clean, well-shaped story. The best interactive fiction is dedicated to the service of the story. As it should be.

And yet...

I feel like there's room for a more open-ended experience; one that is compelling more from the joy of exploration than careful plotting, from mystery and emergent phenomena than the satisfaction of puzzle pieces clicking into place.

I don't know that this is the case, nor do I know I'm capable of manifesting it. I'm not even sure what I'm describing, exactly.

Programmable Realities

It probably seems obvious now, but the Quake console kind of blew my mind when I first saw it.

Quake Console

I'd typed idkfa into Doom before, and a couple of other games where you could type strings into an un-spellchecked void and possibly be rewarded with more health or bullets or whatever, but the Quake console was obviously different. It was a whole thing that came down from the top of your screen and even stayed there after you entered a command. It had its own inscrutable syntax. If you typed "give health", then... well, it didn't react exactly as you expected, but it did something. Sitting there in front of your beige PC with a printed out cheat sheet, you could do some very interesting things, some productive, some not-so-productive.

Much more impressive (honestly, I still barely know how to use it) is Minecraft's console:

Minecraft console

Minecraft's console allowed you to do more than just give yourself health or move you -- it seems to provide the ability to control most of the game.

But all of this probably pales in comparison to the in-game scripting made possible by e.g. LPMUDs, which are intended to be developed by the people playing them, even (sometimes) while the application is running.

At some point, I decided that if I ever made a game, I'd thoroughly integrate a scripting language.

The uses are many:

  • scrutiny of objects during the development process for debugging, etc.
  • scripting objects for automated tests
  • modifying behaviors at runtime
  • loading scripts to modify app or object behavior
  • etc.

Some time back, while taking one of my several abortive attempts at a roguelike, I became aware of Robert Nystrom, and greatly enjoyed his first book, Game Programming Patterns.

Imagine my joy when I saw that he'd written a book, Crafting Interpreters, consisting of an intensive walkthrough of writing a programming language interpreter and compiler!

So I made the decision to use Bob's Lox language as a foundation for my own language.

Of course, that's only the beginning; I need to extend the language to increase its usefulness, and I need to build out the standard library. And, once that is complete, I need to make it so that other parts of this system are able to provide their own innards for consumption to running scripts.

(Actually, I think performance is enough of a concern that I'll just use Lua. Possibly I'll shift to a custom language eventually, but that's difficult to envision given Lua's strengths.)

But for now I'm going to switch focus again...

Dungeons and the Underdark

In keeping with the general weirdness and paucity of the rest of my video gaming experience in the 1990's...

When people talk about dungeon crawlers, I don't so much think of Eye of the Beholder or Diablo or Ultima Underworld or The Bard's Tale. Rather, it's Wizardry VI: Bane of the Cosmic Forge.

Bane of the Cosmic Forge

And only that one, because I've never actually played any of the other Wizardry games.

Bane of the Cosmic Forge, like Zork and The Goonies II, fits into the large category of games that I never managed to beat without a walkthrough. It's another ridiculously difficult game.

It's like Zork in that it assumes that you are carefully mapping every move you make. It's also like Zork in that it will cheerfully allow you to render the game unwinnable. Unlike Zork, it doesn't have the mechanism of the lantern's batteries limiting the amount of time you're actually able to play the game. In my case, I played the game for, I think, a few years without realizing I'd managed to jam a door that was critical for further progression. Every once in a while I'd start playing the game, mosey around the dungeon a bit, and not make any progress, and of course blame myself for my stupidity.

Sir-Tech also had a phone line you could call in for hints. I don't recall them doing me much good.

But this isn't really about my grievances with ridiculously difficult relics, but what I actually find enjoyable and compelling about these games.

Sidenote: I recently played through the three Zork games with my kid. I still needed walkthroughs. And he was, like me, baffled by the puzzles and mazes and frustrated that they even made it into the game. I explained that the thinking at the time was that you were going to be mapping the game with pen and paper as you played it, but I'd never realized that when I played them. All the same, that doesn't seem a terribly satisfying rationalization to me, 25-30 years later.

No, I really enjoyed the atmosphere and the structure of the dungeon, and exploring it. It's true that every bit of the dungeon looked like every other bit of the dungeon. And in fact the belfrey and the mines and the River Styx and the pyramid and even the damned forest looked like every other bit of the dungeon, which is... kind of amazing now. How hard would it have been to make a second tileset?

But I digress.

In some areas, particularly around the castle towers, there were lovely bits of text as you explored.

You hear some kind of rustle or flap from somewhere nearby...

Even in the graphical CRPGs of the time, they frequently had to add text to fill in the details of what the characters were experiencing. And it's those bits of text that really made the dungeon interesting.

Plumes of smoke arise from fiery pits far to the west, testament to an era which should have passed long ago...

Seriously, what is that about? Of course, you can't ask, because you don't have any kind of prompt except in the brief dialogues you can enter with a few of the NPCs.

I think it's worth thinking about Zork, a dungeon crawler text adventure, Bane of the Cosmic Forge, a first-person dungeon crawler, an LPMUD like After the Plague II, and the general Rogue-like top-down grid-based dungeon crawler. Compare and contrast. Discuss their strengths and weaknesses.

Zork has by far the most interesting environments, but it cannot graphically render them. Similarly, an LPMUD can have quite wonderful environments, better than Zork's conceivably, but in practice this is limited by the literary abilities of the users crafting the MUD. Bane of the Cosmic Forge and Rogue are similarly limited to extremely repetitive views, and both can conceivably lean on text to add a bit of flavor that would otherwise be lacking.

Bane of the Cosmic Forge offers a traditional RPG combat system, while Zork had a very limited system that has, apparently, fallen by the wayside as interactive fiction has developed. Rogue has a highly technical combat system, similar to Bane of the Cosmic Forge, and it's turn-based (which tends to appeal to a more methodical mindset, I think). A MUD has a realtime combat system with cooldowns and rate-limiting to avoid cheating, which makes it more like an action RPG like Diablo or EverQuest.

Frankly, mapping is a bore, and I doubt most people did it even when Zork or Bane of the Cosmic Forge came out. Of course, you have to just to be able to beat the damned games. Rogue is king here because it does the mapping for you. That's... maybe the only thing that makes them tolerable. MUDs often benefit greatly from mapping, but some MUD clients offer automapping, and the MUD is generally designed to not require mapping, being as it is crafted by people who don't like mapping any more than you do.

I've contemplated having this game switch to a roguelike interface when in dungeons/dwarven kingdoms/underdark, but I feel like that's a cheap, easy answer that also happens to be wrong. Part of what I don't really like about roguelikes is the endless screens of empty rooms with ridiculously long hallways and little or nothing in the way of character. Sure, there are exceptions, like Brogue, which I have to say is gorgeous...

Brogue

Brogue

But still incredibly repetitive.

Now, when I was 14 or 15 or something, I started making an open-world interactive fiction game with TADS and I think I stopped because I couldn't find a Pascal compiler, which I needed because I wanted to increase the constant for the maximum number of rooms allowed, which I wanted to do so I could create like a thousand rooms that were nearly identical forest or grassland or whatever. I really wanted you to feel that open world.

I'm no longer that big of an idiot.

But the fact remains that repetitive text rooms are just as bad as repetitive dungeon rooms. Probably incalculably worse, actually, because you have to go to the effort of reading a room description and realizing it's the same damned thing you've already read. At least with a roguelike you can pick it up at a glance, and see the l that means there's a fire lizard on the other room about to attack you so there's at least something interesting.

The point is that I don't think that simply writing a text version of a roguelike dungeon crawl is going to be a satisfying (or even bearable) experience. And that I really, really have to be careful with repetition in room descriptions. Every room needs to at least feel as though it was created with intent.

One thing I like about Zork, and which I think is necessary for a text dungeon crawl, is that rooms all have some unique descriptor. The Loud Room. The Dome Room. The Carousel Room. The Damp Passage. The Treasure Room. Not all rooms are like this, of course, but I think almost all rooms are at least this distinctive.

This is a difficult idea to translate into the open world. The real world is repetitive. So why wouldn't an open world, even in a fantasy game, be similarly repetitive? But the moment a player types "w. w. w. w. w." and passes through five identical (or even similar) rooms, they're going to quit the game and never pick it up again. And understandably so. I would too! That doesn't fill me with a sense of awe and wonder at the scale of this world/forest/dungeon/cavern. It fills me with irritation that the developer has so little regard for my time.

Cosmos and Tatooine

It's more of a "huh, that's interesting" moment than the amazing shot of the Star Destroyer pursuing the Corvette, and nowhere near as bizarre as the Cantina scene, but the depiction of Tatooine with two suns has stuck with me. We tend to connect that with Tatooine's barrenness and inhospitality. It just makes sense.

Tatooine

Connected with this, the ideas of what other worlds might look like from Carl Sagan's Cosmos: strange organisms like hot air balloons, caves overlooking cold oceans, moons of gas giants... I can't remember which were things he described and which were painted by artists.

Of course, now art from speculative fiction, art from imaginary worlds, it's immediately accessible. Thirty-some years ago it was highly curated, shall we say. A planet with two suns, or an icy waste orbiting a white dwarf, was just about as good as it gets.

I'm at best a middling mind and not likely to create a world with actually realistic and thought-provoking species. Silicon-based organisms that breathe through their butts and have four rods and seven cones and three legs or whatever. I'm fine with that, because this is a text-based game, after all, and I don't want to say things like:

A flormgas enters from the west.

>l flormgas

The flormgas is a silicon-based organism that breathes through its anus.  
Its vision is exceptionally sharp and rich, owing to its four rods and seven
cones.

The flormgas waves its third leg at you menacingly.

The flormgas unsheathes its sponcül and swings it at your head!

Ultimately, this sort of text game needs to convey what is happening concisely, and I would rather write about goblins and elves and even nightgaunts than the Greater Yuridian Flormgas, however majestic its polyric crest might be.

Nevertheless, I do want to take into account the effects of different astronomical configurations. How might goblins on Tatooine differ from goblins on Yavin IV? Or Hoth?

The astronomy system (formerly known as Starfall) is intended to make this kind of thing possible, by actually generating a plausible habitable star system where an adventure might take place. Create a sun -- or binary, or even a ternary or quaternary configuration. Put a planet in orbit around it, with variable characteristics like axial tilt and mass and composition and albedo and water content. Perhaps give it a moon, or two, or not.

Now: what is the atmosphere like? Does it have seasons? How long are the day, the month, the year? What does the day look like? The night sky?

The Golden Bough

My apologies to Sir James Frazer, because I haven't actually read The Golden Bough.

But I've read a small amount of literature on comparative mythology, watched some conspiracy theory videos (with appropriate skepticism, fear not), and read probably more Joseph Campbell than I should've.

One idea I've encountered is that the story of Jesus is a sort of astronomical allegory, reënacting an ancient solar myth featuring the life, death, and rebirth of a solar deity who warms and nurtures the crops, whose death heralds the depths of winter, and whose return signifies new life for the crops and for humanity.

So what might people believe on a planet with no axial tilt, without meaningful seasons?

What might the religions of goblins look like?

What might the religions of goblins look like if they are traditionally dominated by hobgoblins? If that domination looks more like paternalism or hegemony? Or brutal enslavement?

What might religions look like in fantasy worlds with actual deities? If believing makes a deity real, what deities form?

How might the stars be divided into constellations? Can the stars along the ecliptic form a zodiac?

I think these are interesting questions, and I'd like to try to create some interesting systems for answering them.

The Goblin Village

One of my favorite gaming experiences of all time is from a Hungarian MUD, After the Plague II. I was lost in the woods, southwest of Elements City, walking into dead ends, running low on food, probably walking in circles. I saw (high perception score) a hidden path to the south, between thorn bushes. I walked through (getting cut up in the process), and happened upon this:

Goblin Village

Now, this in itself isn't the greatest thing, but a couple rooms south you find two goblin children who play and fight with one another. If their ball is retrieved for them from a nearby quest, they'll play catch with each other, and with you. If it is winter, and there is snow on the ground, they will have a snowball fight with you. Having a snowball fight with goblin children is a fond memory of mine.

There are other interesting interactions elsewhere in the goblin village. There appears to be a caste system, with some goblins being slaves. Above these are fighters. A cook is an important figure too. There's a shaman – predictably tough – and a huge red-eyed goblin – very tough. They have little scripts that they act out as you watch; a goblin slave grows tired and sits down to rest, then a fighter berates him, and the slave stands up again wearily. Sometimes a fight will start, continuing until one or both pass out from exhaustion (these fights are not, in my experience, fatal, but not for lack of trying).

Throughout, the goblins punctuate the player's experience with mutterings from their own language. This is a simple system: liquid phonemes are replaced with fricatives, etc. Similar replacements are performed for other languages, according to some sensible rules.

Of course, the cracks will become readily apparent. As the player learns the language, individual letters -- not syntax or words -- are transformed. Outside of the simple scripts and their manipulation of the various systems available in the mudlib, there is no meaningful artificial intelligence. The goblins will respawn if they are murdered, so that the next adventurer can raze the village. And the next... and the next...

But it can create meaningful experiences.

Chunking, Pt. I: The Region Graph

This morning I had a dream that I was back in college, at the University of New Mexico, which I briefly attended back in 2000. Weirdly, I was aware that it was 2024, because of an exchange within the dream about which I don't recall anything else.

I was looking for a friend who I knew was attending that school; in the dream, it was Isaac H., but it was very similar to another recent dream I had where I was trying to find Sam W. at the same school. I knew, or at least suspected, that my friend did not want to see me and was avoiding me.

It was the last day of school; finals were taken, but, in some weird throwback to middle school and high school everyone had to attend for one more day. The last day of school was always... lonely. I felt a sense of freedom, of course, all those summer weeks for activities. But it felt empty, and I felt alone. I could feel my friends slipping away from me.

I bumped into some students as I traipsed around the campus. I saw a marijuana dispensary and thought, "huh, that's right, that's legal now," but I didn't particularly want to get high. It made me sad, just thinking about it. I found my way into a basement, and some kids blocked me at the door; there was a party under way, and they didn't feel very charitable. I laughed and told them I didn't drink, but I didn't have a problem buying my own beer anyway.

I woke up sad, feeling like I'd lost everything. Just one of those great big feelings of loss. Part of that is an article I read, shared by my coworker Tanner Heffner in the work Slack, that suggests that we web and web-adjacent developers are heading for more pain, not less; that the job market is lousy but we're in the middle of a tech bubble, and that will burst sooner or later and things will get worse.

Another part of it is that I watched The Super Mario Bros. Movie last night, at the behest of my child. It was a tremendously depressing experience. As was common for members of my generation, I was deeply enchanted by the original Nintendo games. I still remember an overwhelming sense of mystery and awe at seeing Super Mario Bros. 3 for the first time. I remember having a dream about Super Mario Bros. 2 before I ever played it, just from sheer anticipation. And the movie was just... generic. No point going deeper here; the movie never did.

I've been on vacation this week, and I'd greatly anticipated working on Hornvale. That hasn't gone well. It never does. Whenever I get time off, I think, "finally, now I have a chance to get some solid work done."

And what happens is I drive myself nuts. I begrudge every minute not spent on my project, so I put off exercising, eating, socializing, etc. I get increasingly aggravated with each new setback, because I envision a week of code streaming out the tips of my fingers and into rustc and emerging as a perfect unit of functionality that moves me inexorably toward the end-goal of a perfect game.

In reality, it's intensely frustrating, and I never accomplish much at all. And then it's Saturday, and I'm somehow behind where I started the week, with nothing to show for it.

But possibly being in the midst of a bout with depression isn't really what this post is about; it's about Minecraft. In Minecraft, if you don't like where you are, you can just head in one direction or another, and things will change. If it's too steep to the west, turn to the south and go that way for a while. If you find an ocean that way, and don't have a boat on you and don't particularly want to paddle endlessly, turn to the east, or back to the west. There's an endless world to explore.

Of course, the world gets dangerous at night. And you're ultimately going to see the same few environments over and over again. That's not a knock against Minecraft, which is a great (albeit flawed) game. It's perhaps unavoidable. I'm not coming into this with a preconceived solution.

But dreams and Minecraft are somewhat similar in that, no matter where you go, there's something there.

I was startled to re-learn, reading through Internal Secrets of Infocom Games, that Infocom games were limited to a total of 256 objects (which includes rooms). Zork I had 110 rooms and 60 takeable objects. And that game seemed quite large and expansive to me as a child.

But I also remember the keen frustration of stomping through the forests and being blocked by fallen trees. "Aw, c'mon," I thought (and perhaps said) as a 9- or 10-year-old. "I could find my way around that." I wanted to know what was on the other side. Zork I was incredible enough, but I knew that there were other mysteries, other places to explore.

Minecraft, for all its many numerous strengths, doesn't solve this problem. It presents an endless number of places to explore, but none of them are particularly interesting. You can't find bits of lore, like in Skyrim or Baldur's Gate III or most other RPGs, that deepen your immersion in and attachment to the world. (Admittedly, the absence of lore is itself interesting.)

And of course this is fitting into the pattern of roguelikes, most of which will procedurally generate dungeons that don't end up being very interesting. And I've discussed this before. But this isn't much of a project if I just complain about problems instead of trying to solve them interestingly, is it?

So let's state the problem clearly: I want Hornvale to have an essentially infinite procedurally generated world, but I also want it to be interesting. How do we have both?

There are some related problems, though, and the first is, simply: "How do we have an essentially infinite procedurally generated world? Like, at all?"

So this article is about chunk loading, and how I'll handle that in Hornvale.

Hornvale won't have graphics, but I anticipate that there will be a significant computational load for each "chunk"; there will be creatures going about their daily affairs, which will involve some understanding of and interaction with their surroundings: what season is it? what's the weather like? what can I gather from the ground? what squabbles am I involved in? what pressures do I face? my family? my tribe? what do the stars tell the shaman?

So, while I'm not necessarily concerned with all of the rays that need to be drawn to determine what is and is not visible, as I might be with a normal modern game engine, it's still important for me to restrict what is loaded at any given time. But we also need not to absolutely minimize what is loaded; life should go on, albeit a little slower, for chunks that the player is not currently exploring.

On the Nature of a Chunk

A chunk in Hornvale is not like one in most video games, even Minecraft. Rather than moving through a coherent, contiguous 2-D or 3-D space, we're transiting through a graph from node to node. We almost never actually experience the edges, except as obstacles to overcome (doors, puzzles, etc). Our space does not actually need to be coherent.

Zork I map

Consequently, we lose a bit of mathematical consistency but gain a tremendous amount of flexibility. We can simply treat the world as an infinite graph where each node is a chunk, and each node is connected to at least one neighboring node by an edge.

I go into the specifics in more detail in the Specification, but I'll summarize the process here:

  1. Create vertices in a unit Cartesian coordinate plane using a modified version of Bridson's algorithm.
  2. Create a minimum spanning tree to connect the vertices using Prim's algorithm.
  3. Create additional cycles to improve navigability using a simple random function.

That should lead to a graph that looks something like this:

World Example

We are left with regions and straight-line-ish connections between them, which we can use as the basis of our world, and of our chunking system.

Chunking, Pt. II: Chunk Loading and Unloading

Previously, we arrived at a method of generating regions as a connected graph that can grow infinitely in any direction, creating the potential for an essentially boundless explorable world.

In this article, I want to achieve a good understanding of how we can implement a system for smoothly and efficiently loading these regions into the application's working memory when needed and unloading them when no longer needed, to realize the goal of an infinite world on very finite hardware. This leads us to the concept of "juice," which is an attempt to model the engagement and interest of the player in a given region, and use that to determine how computing resources are allocated.

The dream here is that the player, traveling through the world, will frequently encounter interesting developing situations, and feel compelled to interact in some way. For instance, a human village might be getting attacked by a tribe of bugbears, using goblins as cannon fodder. This sort of situation should arise from the evolution of the situation within each region and between the regions and their neighbors. The connections between regions, the edges between the vertices of our graph, are not just passages for the player to travel but potential avenues for trade, communication, or invasion.

So we will know if we have this algorithm tuned smoothly if a player wanders into a chunk and feels as though they have arrived "just in the nick of time." We can fudge this a bit by decreasing the offensive power of attacks when the player isn't present (although not to a degree that it strains belief) and by noting, but simultaneously diminishing, the effective disparities of power within and between regions. Thus, things tend to happen when the player is around, and not happen so much when they're not around.

I call this "juice" in the sense of gasoline or energy. The region currently occupied by the player has the highest juice; those neighboring have somewhat less, and those at a higher degree of separation have still less. Juice "lingers" after a player leaves a region; if the player leaves a nasty situation, we don't want to just pause it until they get back. We want them to return and see the aftermath.

When a region's juice is sufficiently low, there's no reason to keep it in memory anymore. Then it can be unloaded.

We can describe Jcurrent, the total current juice of the region, as follows:

  • Jcurrent = wproximityJproximity + wlingerJlinger
    • wproximity is some fractional weight for the proximity factor
    • wlinger is some fractional weight for the lingering factor
    • Jproximity (d) = J0e-λd
      • Jproximity (d) is the juice level at distance d
      • J0 is the juice level at the player's location
      • λ is the decay constant, determining how quickly the juice level decreases with distance
      • d is the distance from the player’s current position.
    • Jlinger (t) = L ÷ ( 1 + e-k(t - t0) )
      • Jlinger (t) is the juice level at time t
      • L is the maximum juice level
      • k is the steepness of the curve, determining how quickly the juice level falls off
      • t0 is the time at which the player leaves the region, serving as the midpoint of the sigmoid curve

If Jcurrent falls below some threshold value Jmin, the region is declared to be effectively devoid of interest and can be unloaded until such a time that its juice once again exceeds that threshold.

The following visualization simulates these changes to Jcurrent; the character moves between chunks, and chunks are loaded (invisible -> visible) and are unloaded (visible -> invisible).

Jcurrent changes

In addition, we can also monitor a longer-term cumulative trend:

  • Jengagement = Jengagement + Δ Jt
    • Jengagement is a cumulative measurement of how much a player has engaged with a region.
    • Δ Jt is a measure of how much the juice has changed this turn. This will always be at least zero, though it may be rounded down to zero judiciously.

And we can compare the current state to that historic trend:

  • Jdecay = Jengagemente-λ(t - t0)
    • Jdecay is an indicator of how much a player has engaged with a region recently
    • λ is the decay constant, determining how quickly the juice level decreases with time since last engagement
    • t0 is the time at which the player last interacted with the region

This can be used as a trigger for "hey, remember me?" type events:

  • the player receives a letter/newspaper/warning/threat/bounty hunter from a person in $region
  • a loose end from the current quest ties off with a loose end from a quest in $region
  • etc

That's not particularly important right now; we'll deal with other aspects of chunk management moving forward.

Terrain Generation, Pt. I: Elevation

In Chunking, Pt. I, we figured out a way to generate a world map as a planar graph, using Poisson disk sampling and Bridson's algorithm to generate vertices, Prim's algorithm to create a minimum spanning tree connecting them, and injecting vertices semi-randomly to add cycles and improve navigability and nonlinearity.

In Chunking, Pt. II, we devised a system, "Juice," that used some proxies for player engagement (proximity and recency) to determine how to allocate computing resources to regions; not just loading and unloading them as chunks, but making agents more active, battles more violent, and so forth.

In this article, the first in a series about terrain generation, we will begin to discuss how each region's physical attributes are generated and refined.

We first generate Simplex noise for elevation; elevation is affected less by other aspects, such as temperature and moisture, although we may revisit it. For increased realism, we generate multiple octaves of noise, which is to say that we first perturb a flat plane into some broad and simple wave, then revisit it at twice the level of detail but perturb by half as much, then revisit it again at twice the previous level of detail and perturb by half as much.

Elevation Map

This may not seem like much, but we will go a bit deeper on subsequent steps.

Terrain Generation, Pt. II: Temperature

In Terrain Generation, Pt. I, we generated an elevation map for our region. Elevation is, at least for our purposes, a rare "independent variable" for generating terrain. I'm not terribly concerned with erosion or the surface of the world being carved by waterflow. This is just a text adventure, after all. But elevation has numerous effects on other aspects of terrain generation.

The first of these is temperature. A base temperature map can be generated with Simplex noise composited with a latitudinal effect, so that regions closer to the poles are colder and regions closer to the equator are warmer.

Temperature Map

I think that looks pretty nice. A little bit of random variation, in a reasonable range of temperatures (~-10º-90ºF) for a spring day across several biomes, from a harsh desert (Death Valley is about 80º in March) to an icy waste; many places on Earth get considerably colder than this, but I'm not particularly interested in simulating them.

We can then adjust that for elevation by calculating a lapse rate (the drop in temperature per unit increase in elevation change). Because this is a game, and we want to have a variety of biomes in short distances from one another, we can magnify this so that we end up with snow-capped peaks not terribly far away from a desert, but we can tweak this to shift the balance between dynamism and realism.

Temperature-Adjusted-for-Elevation Map

We can also determine highs and lows, and report how the temperature changes throughout the year, but these are not terribly interesting to look at, as they're mostly just changes in the numbers; the graph continues to look more-or-less the same.