Monday, March 23, 2020

[rcgmntpz] Generating many random rooms

We consider randomly generating an infinite collection of rooms joined to each other, for an adventure game.

Every room must have a unique identifier.  This identifier, probably hashed, is used to seed a pseudo random number generator to generate characteristics about the room.  The characteristics of a room are generated (or regenerated) from this seed on the fly each time the player visits or revisits the room.  Because the seed for a given room is always the same, the room is generated the same way each time it is visited.  This vastly (exponentially) decreases the storage necessary to keep the room looking the same each visit.

By default, rooms don't save their state between visits.  Such a feature could easily be added afterward, but we don't explore it here.

The connections between rooms form a graph.  Two graph types are easy to implement: a tree and a grid.  For a tree, the unique identifier for a room is the path to it from the root.  The size (storage requirement) of a path is logarithmic in the size of a full tree to that depth.  For a grid, the unique identifier is coordinates.  The size of coordinates, written in a base greater than unary, is logarithmic in the size of the whole grid to that distance.

There are plenty of technical and aesthetic details remaining for designing and decorating a room with its random number generator.  For example, add enemies and treasure.  Add geometry, perhaps locally approximating the twists and turns of a maze.

Items in a room might want not just random numbers generated by the room but their own random number generators.  For example, consider an enemy in a room whose behavior is random.  Should its behavior depend on what other randomly-behaving items in the room the player has already interacted with?  If not, the enemy needs its own random number generator independent of what samples have been taken from the room's RNG.  This is easy to do: seed the enemy's random number generator with a tuple consisting of the room's globally unique identifier and the enemy's identifier unique within the room.  This yields a deterministic enemy, behaving the same each time, keeping with the tradition of many computer games: a player can learn to fight an enemy by learning its deterministic moves.  We can further easily extend this idea of room items having their own RNG to items inside items, etc.

From here, a developer could add restrictions on what the player can do and where the player can go.  Or not: this could be the ultimate open-world game within which players must invent their own adventures and choose their own difficulty.

Future post: prototype implementation.

Nodes near the tree root or close to the grid origin are a central region that all players first explore.  For trees, they are also a nexus through which players must frequently travel to get between distantly separated parts of the tree.  This shared common experience could induce a gaming community.  This central region could be hand-crafted.

No comments :