- Markdown will now be validated as part of Github CI - Applied auto-fix to most common issues (mostly whitespace related) - Fixed manually some of more complex cases Some valid markdownlint rules are currently disabled, to avoid failing CI, can be enabled in future
4.7 KiB
RMG Description
Fundamentals
Random maps are represented by undirected graph of zones linked with connections.
On maps with water, a single extra water zone is created.
Modifiers
Zone filling process is split into multiple phases, each of them represented as a modifier. A modifier can require other modifiers to finish their job before launching. A modifier might be preceded by other modifier from every zone, or many modifiers from all zones. For instance, placing underground rock requires all underground zones to finish treasure placement first.
Thread pool
A queue of Modifiers jobs is created in roughly topological order, so that Modificators with no dependencies are placed first. The queue is iterated in a circular manner and if Modificator with no remaining preceders is found, it is picked for execution in a separate thread. After job completion, Modifier is erased from dependencies of Modifiers which depend on it.
Placing Zones
Generating distance graph
Based on zone connections, a simple distance graph is created using Dijkstra algorithm.
Initial zone placement
Based on distance graph, zones are placed one by one on N x N grid of size just enough to fit all the zones (for instance, 5 zones are placed on a 3 x 3 grid and 24 zones on 5 x 5 grid). Adjacent zones are placed close while distant zones are placed as far away from each other as possible.
Iterative optimization
Finally, zones are moved from their initial positions using Fruchterman-Reingold algorithm. It assumes all the zones are soft spheres, which attract connected zones as springs but push back not overlapping zones crossing their borders. These forces are summend and determine the vector shift of the zone position. The algorithm uses classic "simulated annealing" approach - zones start with high "temperature" (are very soft and squishy) and then gradually become colder (harder) and push away overlapping zones with stronger force.
To prevent getting stuck in local minima, sometimes most misplaced zones swap placed manually.
Penrose Tiling
Using iterative subdivision, a set of Penrose tiling vertices ic created at random orientation and centered over middle of the map. All the tiles on a map are assigned to the closes vertex. Then, every vertex is assigned to the closest zone, creating irregular shapes.
Zone connections
Directly adjacent zones are connected with a guard and a road, and overlapping zones on different levels are connected with Subterranean Gate. Zones which are not directly adjacent might be covered through water zone. If a zone shouldn't be connected with nearby zones adjacent to body of water, it's coast is sealed with obstacles.
Water routes
TODO
Fractalization
Every zone starts with at least one free tile in the center. Now, from every tiles at a distant greater than some number, a random tile is chosen. From it, algorithm routes a free path connected to already existing free paths. Process is repetaed until no tiles distant from free paths are left. Tiles used for connections are marked free
and nothing else can be placed on them.
Zones with type junction
are not fractalized.
The remaining tiles that are not obstacles (such as zone edges) are marked as possible"
so they can be either filled with treasures or left free.
Treasures
Every object or treasure pile in the zone is placed as far away from existing objects as possible. This includes towns and zone guards placed first. Zone keeps a priority queue of tiles sorted by their distance to closest object. Whenever an object is placed, these distances are updated.
Treasure generation
Treasures are separated in value ranges. The highest range is picked first. A large number of treasure piles is generated, then RMG tries to fit each of treasure piles into a zone. Then, lower treasure ranges are generated
Treasure placement
New treasure pile can't be closer to any previous object than some distance determined by total treasure density and value. Lower value piles and placed with lower minimal distance.
Any new treasure is placed so that it can't join two previously separated blocked islands, to prevent sealing a gap and ensuring entire zone is passable.
Obstacles
After all the treasures are placed, tiles marked as possible
are iteratively stripped and cleared from lose appendages, leaving free
space. Then remaining ones are marked as blocked
, and covered with obstacles.
Biomes
For every zone, a few random obstacle sets are selected. Details
Filling space
Tiles which need to be blocked
but are not used
are filled with obstacles. Largest obstacles which cover the most tiles are picked first, other than that they are chosen randomly.