Skip to content

Random map generation

Builds a playable map out of a map seed's twenty settings through a fixed sequence of passes.

Features & systemsScenarios & AIMaps & scenarios

A map seed is not a map. It carries no cells, no tiles and no waypoints — only twenty settings, out of which the generator lays down terrain, water, cliffs, roads, buildings, tiberium and one starting position per player. Map seed files owns the file itself: how it is recognized, what its one section is called, and why the two size settings are indices rather than cell counts. This page owns what happens once it has been read.

Two things govern everything below. The passes run in one fixed order and each consults a known handful of the twenty settings, so a setting that appears to do nothing is usually a setting whose pass this particular seed never reaches. And every random choice made anywhere in generation comes from one sequence started from Seed, so two maps built from identical settings come out identical cell for cell, and altering any setting that changes how many draws an earlier pass makes changes everything after it too.

A seed reaches the generator by two routes that share the passes and nothing else. The table sets both out; the column that matters most is the last one, because the map a player fights on is never the map the dialog built.

RouteHow the settings arriveWhat is generated
The map generator dialogTaken off the dialog controls, rolled by its randomize button, or loaded from a saved seed and written back into the controls. All three of those actions hold every setting inside its legal rangeA preview. The previous scenario is torn down first — its objects, houses, theater and tile artwork — and rebuilt around the new map, and a thumbnail is drawn from the result
Starting a scenario whose filename ends .SEDRead straight out of the file’s [RandomMap] section, over whatever the generator’s settings currently hold. No range check runsThe map that is played. It is generated into the scenario already being loaded, with no teardown

Accepting the dialog does not hand its map to the game. It writes the settings out to RandMap.Sed and registers that file in the scenario list; the lobby then starts RandMap.Sed as a scenario, and the second route builds the map over again from the same settings. The preview exists to be looked at, and is discarded.

The file extension carries weight beyond the generator, too. Recognizing .SED marks the scenario as a generated one for the rest of the load, which is what keeps a tile set marked RequiredForRMG=yes resident when the loader trims artwork no cell is using yet.

The first pass turns the seed into a blank scenario for the rest of them to work on.

The playable area is measured first. NumPlayers picks a row of minimum and maximum figures and Width and Height each interpolate within that row; the table of figures is on the map seed page. The playfield is then written four cells wider and twelve taller, with the playable area inset two columns and five rows inside it, so the border a generated map carries is fixed and is not a function of any setting.

Biome chooses the theater — tundra and taiga build in snow, temperate, desert and mutated in temperate — along with the fill terrain and a light scale for that theater. Time chooses the hour’s ambient level. Those, the playfield, the playable area and a starting ground level of 4 are written into a scenario held in memory, which the scenario route then reads back as though it were a map file. What comes out is a map every cell of which is clear ground at one height, with a per-cell working grid allocated beside it to hold the region numbers, heights and ground-cover chances the later passes accumulate.

Two settings pull outside material in at this point, both of them before a single cell of terrain is placed:

One draw is also made here rather than in the pass that uses it: whether this map’s rivers may end in a waterfall is rolled once, at one chance in four, and holds for the whole map.

The table lists every pass in the order it runs, with the settings each one consults. Two things are worth reading off it. The hills are raised late — after the tiberium, the towns and the roads are already down rather than before them — so the ground those passes chose is not quite the ground that ends up beneath them. And Description appears nowhere: it is the one assignment of the twenty that no pass reads.

PassSettings it reads
Sizing and the blank mapNumPlayers, Width, Height, Biome, Time, UseTransitions, UseIonStorms
WaterWaterAmount, Biome
Ice smoothingBiome
Regions, cliffs and rampsRegionSize, Accessibility, Biome
Start points and the layout spreadNumPlayers, TiberiumLayout
FloodlightsTime, UseTransitions, NumPlayers
VeinholesVeinholeMonsters, Biome
TiberiumTiberium, NumPlayers, UseBlueTiberium, TiberiumWildlife
SettlementsUrbanPresence, Biome
HillsRuggedness
Ground coverVegetation, Biome, Width, Height

Most of those passes can be skipped outright, and nearly every condition that skips one is the biome. The table below gives each condition, so a reader whose setting appears to do nothing can check first whether its pass ran at all.

Pass or branchRuns only when
The water pass as a wholeWaterAmount is above 0
The river within itWaterAmount is above 20, and the biome is not desert
The arctic lake and river, which lay iceThe biome is tundra — taiga uses the ordinary ones
Ice smoothingThe biome is tundra
Region splitting, which is where a generated map’s cliffs come fromThe biome is not tundra
VeinholesThe theater is temperate, so never on tundra or taiga
Creatures in a tiberium fieldThe Firestorm addon is present, and the field is not one of the start-point fields
Urban areasThe biome is temperate, desert or mutated
Rural settlementsThe biome is tundra or taiga
Mold and crystal growthsThe biome is mutated
The hill height walkRuggedness is at least 2

The water pass spends a budget rather than filling a proportion. The budget is WaterAmount multiplied by the playable area and by a factor chosen per biome, with a hundred cells added on top, and the lake and river routines spend against it and stop when it runs out.

A river is attempted first, up to ten times, and only on a wet enough map that is not desert; a lake follows, also up to ten times. Tundra uses arctic variants of both, which lay ice rather than open water and are what the ice smoothing pass afterwards has to blend into the ground around them; taiga, though it is also a snow-theater map, gets the ordinary lake and river and no ice at all. On the mutated biome up to two stretches of a lake are then soured into swamp. Both routines read the theater’s WaterSet to decide what already counts as water, and a river that reaches a drop in height may finish in a waterfall where the once-per-map roll allowed one.

The pass leaves the map’s water recorded as regions in the working grid rather than as loose cells, which is what lets the next pass treat a lake as a single object and span it with bridges.

A region here is a group of connected cells that the generator holds at one ground height. The pass builds them in three stages.

The water just laid becomes regions of its own first, each grown four rings outward and allowed to absorb the ground it reaches. Everything left over is then carved into land regions. Finally, any dry region larger than the limit RegionSize sets is split in two with one half moved to a new height, and the splitting repeats until nothing oversized is left. The cliff faces of a generated map are a by-product of that last stage — nothing places a cliff directly — and the stage is skipped altogether on tundra, which is why the setting changes nothing there.

Once the heights have settled, every region works out which regions it borders and connects itself to them. A water region spans itself with bridges to the dry land on either side, and only where both sides stand at the water’s own height. A dry region instead carves ramps down to each lower neighbor: one ramp is always asked for, and Accessibility is the chance, rolled once per pair, that the pair asks for one or two more. The artwork comes from the theater, and the roles that describe rock face — CliffRamps among them — are what tell the generator which tiles it must not build over while it works.

The start points are chosen only now, out of the finished terrain, and they are chosen together with the tiberium field sites.

Fifteen candidate cells per player are gathered from the large regions that are mutually reachable, each candidate needing a ten-by-ten block that a paved road could be laid in and a position at least four cells inside the playable area. The most widely separated of those candidates are then picked out as a single spread, with cells lying in different regions treated as further apart than they are so that the picks favor separate pieces of ground. The first NumPlayers cells of that spread become the start waypoints; what remains of it is the tiberium layout, and TiberiumLayout is what decided how long the spread was to begin with.

Each start point then has to flood exactly four hundred clear cells around itself. Every cell that flood reaches is marked protected — a per-cell flag the later placement passes avoid, which is what keeps towns, veinholes and ground cover out of a player’s opening room. If any player’s flood runs dry short of four hundred, the whole selection is thrown away and made again from the next state of the random sequence, with the terrain kept as it stands. Nothing caps that retry.

Three placement passes follow, in this order.

Floodlights. Each start point is ringed with civilian lights, in a number Time fixes and UseTransitions=yes overrides. A ring goes down only where every light in it can legally stand, and twenty-one ring angles are tried before a start point is left dark.

Veinholes. VeinholeMonsters monsters are asked for, with at most two hundred attempts made in total, so a crowded map simply ends up with fewer of them. Each attempt draws a cell and accepts it only when all of these hold, in this order:

  1. The five-by-five block centered on the cell, and the ring of cells around that block, lie within the playable area.
  2. All of:
    • no cell of the block is protected ground;
    • every cell of the block is clear tile, stands at the block’s own height, and carries no overlay.
  3. The veinhole placement test accepts the cell.

An accepted cell takes the veinhole overlay, its eight neighbors take the dummy overlay, and the border of the block is given a starting ring of veins.

Tiberium. Every cell of the layout spread is grown into a field, and then each player is given a compensating field at their own start point. That field’s size is the difference between the player’s mean distance to the layout sites and the smallest such mean among all the players, multiplied by fifteen, plus a flat five hundred — so the player sitting farthest from the map’s tiberium gets the largest field on their doorstep and the closest player gets the bare five hundred. Tiberium sizes the layout fields and TiberiumLayout counts them.

A field grows outward from its site over open ground, thickening tiberium already there rather than overwriting it, and starts over from its origin up to ten times if the growth stalls early. Which overlay set it grows is settled per field: with UseBlueTiberium clear every field grows the first set, and with it set each layout field is rolled for separately. The start-point fields are handled differently — one roll covers all of them, so every player’s opening field grows the same set as every other player’s, and that same roll also decides whether a tiberium tree is planted at the heart of each.

UrbanPresence buys different things on different biomes. Tundra and taiga get rural settlements: a dirt road junction on open unprotected ground, a handful of civilian buildings along the roads grown from it, and a few civilian vehicles. Temperate, desert and mutated get urban areas: a paved district flood-filled outward from a cell, with its own road network, buildings, traffic and a pavement blend around the edge. Both branches give up after ten attempts however many were asked for, and the key page covers what that ceiling does to the range.

Both draw their road pieces from the theater. The rural branch works from a library counted off DirtRoadCurve and opens each network on a shape from DirtRoadJunction; the urban branch lays numbered pieces counted off PavedRoads and caps each run with a piece from PavedRoadEnds. Neither branch ever selects a ramp piece, which is why DirtRoadSlopes and PavedRoadSlopes are inert and a generated road stops at a slope rather than climbing it.

The hills come after all of the above. Cells beside a shoreline or a cliff face are pinned down first and keep the heights they already hold, so the walk that follows cannot raise a hill into the water or bury an existing cliff. That walk then sweeps the map giving each cell a height drawn from the neighbors already settled, with Ruggedness fixing both the size of each step and how far the walk may wander around it, and the terrain is finally stepped up or down one level at a time to meet the result, the smoothing system cutting slopes and ramps in as it goes. Below Ruggedness=2 the walk is skipped and no cell is given an offset at all.

Ground cover is last. Each cell is first given four chances — green ground, rough ground, sand and woods — of which Vegetation scales the green and the woods alone, and those two are multiplied tenfold again along a shoreline; each cell is then rolled against the four in that order, the first to come up deciding what the cell gets. A cell is considered only while it is clear tile, carries no ramp and no overlay, has nothing standing on it and is not protected ground. A mutated map has its mold and crystal growths laid down before this, in numbers derived from the two size indices, and desert and mutated maps also get a scatter of loose rough ground first. The pass finishes by fixing up the transition tiles and littering the map with rock overlays.

The generator carries no terrain artwork of its own; it works entirely through the roles a theater control file declares. The table groups those roles by the pass that needs them, so a modder adding or renumbering tile sets can see which part of generation a missing role would reach. Theater control files explains how a [General] role is resolved to a live tile index.

PassRoles it consults
Water and iceWaterSet, the shore, waterfall and swamp sets, Ice1Set, Ice2Set, Ice3Set, IceShoreSet
Regions, cliffs and rampsThe cliff, slope and ramp sets, CliffRamps among them
SettlementsPavedRoads, PavedRoadEnds, DirtRoadCurve, DirtRoadJunction, and the pavement and median sets
Ground coverThe green, rough, sand, rock, mold and crystal sets

Tile artwork is trimmed as a map is read, by counting how many cells use each type and discarding the artwork of every type the count leaves at zero. A generated map places most of its tiles after that count has been taken, which is what RequiredForRMG=yes exists for: it exempts a set from the trim, but only on a map the loader knows is generated, and recognizing the .SED extension is what tells it that.

When the last pass finishes, the vein and tiberium growth and spread systems are started, the working grid and the region records are thrown away, the map’s overpass and radar image are computed, and the finished map is handed back to the scenario load already in progress.

Only then do the multiplayer fixups run. They are deliberately held back while a generated scenario is being read, because until generation finishes there is nothing for them to work on: each house’s starting force is created at the start waypoints the generator wrote, crates are scattered if the session asked for them, and computer houses take their credit multipliers. A generated map is an ordinary scenario from that point on.

Two lobby-side reads happen before any of this and are worth naming here, because both look at the seed file rather than at a map. The multiplayer and skirmish lobbies check that the chosen scenario has somewhere to put everybody by counting its [Waypoints] entries, and fall back to reading NumPlayers when it has none — which is always true of a seed file, whose start points do not exist until the map is generated. And a saved seed is identified, both in the lobby and in the dialog’s preview cache, by a digest taken over the settings that stops short of UseTransitions: two seeds differing in nothing but that flag are treated as the same map.

39 of 39

KeyDescriptionValueWhen omitted
Accessibilityrandom map generationThe chance that neighboring pieces of high and low ground are joined by more than one ramp, as a figure from 0 to 100.integerUnchanged
Biomerandom map generationThe kind of country a generated map is laid out in, as a position from 0 through 4.integerUnchanged
CliffRampstile controlsTile set holding the theater's twenty cliff ramp pieces.integer-1
DescriptionCampaign, map packets, multiplayer maps, random map generationThe text a campaign, a multiplayer map, or a saved map seed is listed under.stringVaries by type
DirtRoadCurvetile controlsThe tile set the whole run of 101 flat dirt road pieces is counted from.integer-1
DirtRoadJunctiontile controlsThe tile set that supplies the eleven dirt road junctions.integer-1
DirtRoadSlopesNo effecttile controlsThe tile set that supplies the eight pieces carrying a dirt road up a ramp.integer-1
HeightBuildingType, SmudgeType, random map generationA structure's vertical extent, the number of cell rows a smudge covers, or a generated map's size index.integerVaries by type
Ice1Settile controlsFirst of the three sixty-four-tile ice sets a snow theater provides.integer-1
Ice2Settile controlsSecond of the three sixty-four-tile ice sets a snow theater provides.integer-1
Ice3Settile controlsThird of the three sixty-four-tile ice sets a snow theater provides.integer-1
IceShoreSettile controlsForty-eight-tile set of the land-side pieces laid where ice meets ground.integer-1
IonAmbientscenarios, random map generationThe overall light level in force while an ion storm is running, where 1 is full daylight.floating pointContext-dependent
IonBluescenarios, random map generationThe blue palette tint in force while an ion storm is running, where 1 leaves the blue channel unchanged.floating pointContext-dependent
IonGreenscenarios, random map generationThe green palette tint in force while an ion storm is running, where 1 leaves the green channel unchanged.floating pointContext-dependent
IonGroundscenarios, random map generationThe flat darkening subtracted from every cell while an ion storm is running, as a fraction of full light.floating pointContext-dependent
IonLevelscenarios, random map generationThe brightness added per height level while an ion storm is running, as a fraction of full light.floating pointContext-dependent
IonRedscenarios, random map generationThe red palette tint in force while an ion storm is running, where 1 leaves the red channel unchanged.floating pointContext-dependent
NumPlayersrandom map generationThe number of players a generated map is built for, and the number of start positions a lobby credits it with.integerVaries by type
PavedRoadEndstile controlsThe tile set that supplies the four caps that close the end of a paved road.integer-1
PavedRoadSlopesNo effecttile controlsParsed tile set of paved road ramp pieces that nothing consults.integer-1
PavedRoadstile controlsThe tile set the fifteen tiles counted as paved road are counted from.integer-1
RegionSizerandom map generationHow large a piece of ground a generated map may hold at one height before it is broken up, as a figure from 0 to 100.integerUnchanged
RequiredForRMGtile controlsTile set whose artwork is kept in memory on a generated map even while no cell uses it.booleanno
Ruggednessrandom map generationHow hilly a generated map's ground is, as a figure from 0 to 100.integerUnchanged
Seedrandom map generationThe number the map generator's random sequence is started from.integerUnchanged
TiberiumOverlayType, WarheadType, random map generationMarks an overlay as Tiberium, lets a warhead set Tiberium off, or sets how much Tiberium a generated map receives.booleanVaries by type
TiberiumLayoutrandom map generationHow many tiberium fields a generated map is given, as a figure from 0 to 100.integerUnchanged
TiberiumWildliferandom map generationHow readily a generated map's tiberium fields are given creatures to guard them, as a figure from 0 to 100.integerUnchanged
Timerandom map generationThe hour a generated map is fought at, as a position from 0 through 3.integerUnchanged
UrbanPresencerandom map generationHow built up a generated map is, as a figure from 0 to 100.integerUnchanged
UseBlueTiberiumrandom map generationGrows some of a generated map's fields from the second tiberium overlay set rather than the first.booleanUnchanged
UseIonStormsrandom map generationWhether random map generation folds the ion storm file into the map it builds.booleanUnchanged
UseTransitionsrandom map generationLets a generated map's lighting move with the hour instead of holding the hour it was built at.booleanUnchanged
Vegetationrandom map generationHow thickly a generated map is planted with green ground and trees, as a figure from 0 to 100.integerUnchanged
VeinholeMonstersrandom map generationVeinhole monsters the random map generator plants.integerUnchanged
WaterAmountrandom map generationHow much of a generated map is put under water, as a figure from 0 to 100.integerUnchanged
WaterSettile controlsFourteen-tile set of open water.integer-1
WidthSmudgeType, random map generationA smudge's width in cells, or a generated map's size index.integerVaries by type