Tiles
A region is land built from standard tiles that snap together, as in RollerCoaster Tycoon: a grid of 64 m tiles whose heights are the levels of their corners. Whoever writes a region's spec names features (a hill here, a mountain there, a plateau) and the solver works out every corner, every tile's shape and every seam, so the level is always consistent and every tile can be walked or driven from its neighbours. This page is the official spec of the tiles: what a tile is, which shapes exist, how features become heights, what a region's spec says and what comes out. The catalogue's source of truth is packages/catalogue/src/tiles.json; the solver is packages/catalogue/src/region/ (its README).
Roads are laid over the tiles too, five classes from a dirt track to a highway, with junctions and bridges. Lakes hold water a person wades and swims and a car sinks in; a volcano's crater holds lava, which may flow down one of its flanks; a ski run is painted down a mountain's flank. Every lake and every volcano comes dressed: a beach and a jetty, a lookout on the rim. A creator writes a region's spec through the MCP server (level_spec_set, which answers with the solver's issues or the region's map at once) and the platform builds it without Blender.
The grid
| Number | Value | Why |
|---|---|---|
| A tile's side | 64 m | Big enough for a block of town, a bend of road or a hilltop; a 16 × 16 region is 1 km across. |
| A level | 4 m | A storey, a gentle step: one level over a tile's side is a 6 % grade, which a car takes in its stride. |
| Levels | 0 to 10 | Up to 40 m. Nothing is ever below level 0, the height of the world's flat ground around a region. |
| Vertices | every 4 m | A tile's mesh is 16 × 16 cells, fine enough for a road's flat bed and a seam that matches. |
Directions are the game's: north is +z, east −x. A corner is [i, j]: the i-th along the game's x (westward) and the j-th along z (northward), from 0 at the region's south-east corner. Tile [i, j] is the one whose south-east corner is corner [i, j].
Corners, shapes and seams
Every corner has one level, shared by the four tiles that meet there. Two corners along a grid line differ by one level at most (two round a mountain). So a tile's four corners, less its lowest, are one of a handful of shapes, each turned any of four ways:
| Shape | Corners (sw, se, ne, nw), less the lowest | What it is |
|---|---|---|
flat | 0 0 0 0 | Level ground. |
corner | 1 0 0 0 | One corner a level up: the foot of a hill seen from its side, or its shoulder. |
slope | 1 1 0 0 | A hillside: 4 m over 64 m. |
saddle | 1 0 1 0 | A pass between two hills. |
three | 1 1 1 0 | The inside of a bend in a hillside. |
steep | 2 1 0 1 | One corner two levels over the opposite one: a steep shoulder. |
mountainside | 2 2 0 0 | Two levels along one edge, 8 m over 64 m: only round a mountain or in a valley. |
A tile's surface blends its four corners, plus a small seeded bump that is nothing on its edges. Along an edge the height depends on that edge's two corners alone, so two tiles always meet: the seam is the same line from both sides, whatever the tiles. That is what the tests hold (region.test.ts: every seam of a region is the straight line between its two corners), and what lets a car cross from any tile to any other with its wheels down (packages/sim/src/terrain-tiles.test.ts, E2E-422).
Features
A region's spec shapes its land with features. Each raises or lowers the corners it covers; the solver then spreads every raise outward a level per tile (two round a mountain) and pins what must stay put, so a peak always gets its sides.
| Feature | Fields | What it does |
|---|---|---|
hill | at (a corner), level (1–10), radius (tiles, level by default), lighthouse, name | A rounded hill, its peak at at, falling a level per tile, wider with a bigger radius. With lighthouse: true a lighthouse stands on its top (a building of the level's own kit, a telescope beside it, the place <name>_lighthouse): a coast's landmark to drive to and photograph. |
mountain | at, level (2–10), radius (half its level by default), name | A mountain whose flanks fall up to two levels a tile within radius. |
plateau | at (its first tile), size ([w, h] tiles, up to 8), level, name | A flat top at level, slopes all round. |
valley | at, radius, level (its floor, 0 by default), name | A hollow down to level, its sides up to two levels a tile. It needs higher land round it: a base, hills. Two side by side make a gorge a road runs across. |
lake | at (its first tile), size ([w, h] tiles of bed, up to 6), level (its shore, 1 by default), name | A lake: its bed a level under its shore, the shore a tile all round it, the water 1 m under the shore (3 m deep over the bed, shallow where the shore's slope comes up). |
volcano | at (its crater's middle), level (its rim, 3–10), radius (its flanks beyond the rim, half its level by default), flow (north, east, south or west), name | A cone whose rim is the ring of corners round at, the crater's middle two levels (8 m) under the rim, its lava 2 m under the rim (a level-5 volcano: the rim at 20 m, the lava at 18 m); the top of the cone bare rock (2.4 tiles round the crater). With flow, the rim is breached a level lower on that side and a flow of lava 12 m wide is painted down that flank to a little past its foot, banks of ash either side. |
ski | at (its top), to (its foot), name | A ski run: snow painted 28 m wide down the line from its top to its foot (on a mountain's flank). It changes no heights. |
Water and lava
A lake's water and a volcano's lava are sheets over a rectangle of tiles at one height (the level's water, a block:water of the recipe): the ground higher than a sheet shows through it, so the water is where the land lies lower. A lake's sheet spans its bed and its tile of shore all round, 1 m under the shore; a volcano's spans the four tiles round its crater's middle. The tiles a sheet spans are wet: no road is routed through them (a road to a lake ends on its southern shore, a road to a volcano below its southern rim) and nothing grows there.
What the game does with them (packages/sim/src/water.ts, sinking.ts): a person in water over the knees (0.45 m) wades at half pace; deeper than the chest (1.3 m over the bottom) they swim, afloat with the head out, at 1.6 m/s, unable to fire or jump, and climb out where the bottom comes up within 0.6 m of their feet; a fall into deep water hurts nobody. A car whose middle sinks 0.6 m under the surface floods: wrecked, everyone in it put out to swim, it settles on the bottom, slowed by the water. A car whose body sits in water (the surface over the bottom of its chassis) neither smokes nor burns: its fire goes out and never starts there. Lava kills whoever steps in and wrecks whatever drives in, setting it alight. The AI never plans a path through water deeper than a wade or through lava (@foi/world's navigation grid). test-water is the mechanics' level (E2E-426 to 428, and E2E-566 and 567 for smoke and fire in water).
Two things are always flat at level 0: the rim (the outermost corners, where the world's flat ground goes on) and the spawn apron (the two tiles in the middle of the southern edge, where the players start unless the spec's start names a town). A feature too close to either is cut short, and that is an error with its path: features[0].level: the hill's peak rises to level 2, not 4: the rim or the spawn apron is 2 tiles away; move it inward, make the region bigger or lower it. A peak of level L needs L tiles to the rim (half that round a mountain); a lake needs its tile of shore clear of the rim and the apron (features[0].at otherwise).
Shores and craters
Every lake and every volcano is dressed with pieces of the street kit (and a few of downtown's), on a random stream of its own, wherever no road runs (packages/catalogue/src/region/dressing.ts):
- A lake: a beach of painted sand along its southern shore with beach umbrellas, sun loungers and a lifeguard's tower; a timber jetty 16 m long out from its southern waterline over the water, two rowboats and a swan pedalo beside it; reeds along its northern waterline. A person walks the jetty dry and steps off its end into the water.
- A volcano: basalt boulders on its cone, four fumaroles round its crater's lip, a lookout on its southern rim (a guardrail, a telescope, a warning sign; 2 m over the lava) and a seismograph's hut down its flank.
The client draws lava with a moving, glowing crust (apps/client/src/renderer/lava-view.ts) and, within 250 m of the camera, smoke rising off a crater's lava and steam off the fumaroles (apps/client/src/renderer/vents.ts). No bundled level has a lake or a volcano: the solver's tests hold them (packages/catalogue/src/region/region.test.ts), and the kit gallery shows them (/?kit-gallery=features).
Roads
Roads are laid over the tiles in the order the spec lists them. Each one runs from where it starts to where it goes through the middles of the tiles' edges, the sockets, as RollerCoaster Tycoon's paths do: straight across a tile, or round a quarter bend of 32 m to the next side. Two classes meet at any socket, so a country road can join a highway in a single tile and need nothing in between.
| Class | Width | Lanes | Speed | Climbs | What it is |
|---|---|---|---|---|---|
track | 5 m | 1 + 1 | 36 km/h | 2 levels a tile | A dirt track: unpaved, brown, no paint. |
lane | 5.5 m | 1 + 1 | 43 km/h | 2 levels a tile | A country lane: paved, one lane shared both ways, no paint. |
country | 7 m | 1 + 1 | 61 km/h | a level a tile | A country road, a dashed centre line. |
street | 9 m | 1 + 1 | 50 km/h | a level a tile | A town street. |
avenue | 14 m | 2 + 2 | 61 km/h | a level a tile | Two carriageways, a solid line between them; its profile smoothed over a tile. |
highway | 18 m | 2 + 2 | 100 km/h | half a level a tile (3 %) | A hard shoulder each side; its profile smoothed over three tiles. |
A road's ends (from, to) are one of these:
spawn: north from the spawn apron. The players start on it, in its northbound lane (unlessstartputs them in a town).- An edge:
north,south,eastorwest, at its middle. The road stops just inside the level's border. - A tile:
[i, j], at its middle. - A feature, by its name: its tile's middle.
- A road laid before it, by its name: the road then ends on that road's centre line, a T junction, in a tile where that road runs straight and no other road meets it.
via lists up to six tiles the road must pass, in order, to lay it where the cheapest way would not go.
tunnels is never (the default: the road climbs over a hill or goes round it) or auto: it may go straight through. See Tunnels.
Routing. The route is the cheapest over the tiles:
- A step costs one, a turn a little more, and climbing more than the class may costs more again.
- A road crosses another only at right angles, where that other road runs straight across a tile. The crossing is at that tile's middle, a junction.
- It never runs along another road, nor back over its own tiles. A road with no way through says so, with its path in the spec:
roads[2].to: no way over the tiles from "highway" to "peak" that crosses the other roads at right angles….
Heights. A road starts from the land under it, then:
- A highway's or an avenue's height closes over every dip narrower than its smoothing span (the land's highest within reach, then the lowest of those), so it bridges a gorge rather than dipping into it.
- The height is levelled so that no stretch climbs faster than the class allows.
- Its ends stay on the land. Where it meets another road it is level with that road across that road's whole width: a flat junction.
Pins too steep for its grade are an error (roads[1]: it meets another road at a height it cannot reach at its grade). So lay the least flexible roads first, the highways, then the roads that cross them.
The ground is graded to the roads:
- Within a metre of a road's edge it is the road's height, a flat bed.
- Beyond that, an embankment or a cutting blends back to the land over 4 to 16 m, and where two roads' beds meet, the wider road wins.
- Where a road runs more than 4 m over the land, it is a bridge. A concrete deck carries it, its top a few centimetres under the road, with railings and piers down to the land every 16 m. The land under a bridge is left as it is.
The level's roads carry their class (RoadDef.kind): the game paints a highway's hard shoulders, the traffic drives them at their speed, and a mission can name them.
Tunnels
A road with "tunnels": "auto" may go through the land instead of over it or round it. Any hill, mountain or plateau it crosses can get one, and one road can have several:
Routing. Climbing more than its class may costs the search little, so it goes straight through.
Heights. It holds its grade under every hump up to about 256 m wide: the land's lowest within reach, then the highest of those, before the grade is levelled. A highway's profile also closes over the dips first.
Where it is a tunnel. The land must stand 6.5 m and more over the road, at its middle and 9 m beyond either edge, for 16 m and more. Elsewhere it is an open cutting.
The ground under a tunnel is cut to the road. Its flat bed reaches a terrain vertex further than elsewhere (5 m past the road's edge), then rises in a steep wall over 4 m.
What is built over it (
packages/catalogue/src/region/tunnels.ts, three pieces of the level's own kit per tunnel,tunnel-<road>-<n>-…):Piece What it is Kind roofThe hill's own surface rebuilt over the cutting, in the biome's colours, a metre thick, a little over the land, its sides going down into the hill A structure. It fades over a player under it ( overhead.ts), carries a player who walks over it, and the AI walks on it.portalsA stone face across each end, the mouth the road's width plus a metre and 5 m high, a lamp either side of it A structure lightsA lamp on both walls every 24 m inside Drawn only. They glow at night, like the street lamps' heads.
Tunnels are opt-in, so a region that names none is built byte for byte as before. test-tiles-tunnel is their level (E2E-498 to E2E-500):
- a highway holds its grade under a mountain in one tunnel of about 200 m;
- a country road goes through two hills in two short ones;
- its contract is
packages/world/src/levels-tunnel.test.ts.
Biomes
A region takes one biome; it colours each triangle of the ground by its height and slope and decides what grows there.
| Biome | Rock from level | Snow from level | Trees | Rocks | What it looks like |
|---|---|---|---|---|---|
meadow | 6 | 9 | a few | a few | Grass, oaks and birches, buttercups |
forest | 7 | 9 | many | few | Darker grass under pines, bluebells |
alpine | 3 | 6 | a few | many | Short grass, rock early, snow on the peaks |
farmland | 7 | 10 | a few | few | Rich green, hedgerows, oaks, fruit trees and poplars, poppies, bales |
steppe | 6 | 10 | rare | some | Yellowing grass, dry patches, twisted and dead trees, stones |
desert | 4 | never | rare | many | Sand and red rock, cacti and the odd palm, dry scrub, abandoned cars |
autumn | 7 | 9 | many | few | Orange and red crowns over grass strewn with leaves |
coast | 5 | 10 | a few | some | Salty grass on pale limestone, pines and palms, sea lavender |
Steep ground (rising more than 11 cm a metre) is rock whatever its height. Trees keep below the rock line; neither grows on the spawn apron.
Rich details
A region whose details are rich looks lived in, out in the country as in its towns (plain, the default, is the ground as it always was):
- The ground is drawn in the biome's several tones (
tiles.json'stones), spread by seeded value noise at three scales (ground.ts): wide drifts of moister and drier grass, dry patches where it is driest, bare earth in small patches, flowers here and there, its rock in two tones. - Its trees grow in a grove or two a tile, of the biome's own kinds (its
flora: oaks and birches in a meadow, pines in a forest, cacti and palms in the desert, autumn crowns, cypresses and palms on the coast). - Every tile out in the country is a plot (
plots.ts), dressed with up to two little scenes of thenaturekit, weighed by the biome (itsdetails) and by the tile: bushes, flowers, boulders, a lone tree with a bench under it, a grove, dead trees, cacti, hay bales, beehives, a woodpile, a run of fence with its gate, a dry-stone wall, a well with its trough, a signpost by the road, a deer stand, a wayside shrine, a picnic table. - Points of interest, two tiles apart at least and one for every fourteen tiles at most, each with a place a mission can send players to: a pond dug into the land with water to wade in (
pond_<n>, only on flat land a level up, away from the roads), a ruin (ruin_<n>), a camp of tents round a fire (camp_<n>), a viewpoint on a hilltop with its binoculars (viewpoint_<n>), an abandoned car (wreck_<n>). A point of interest stands whole or not at all, and its place is a clear spot beside it, off the pieces and the roads.
What a region cannot hold within its budget (3,850 pieces, 392,000 triangles: a third of what a room can hold, REGION_BUDGET) is trimmed when it is written (trimToBudget), the smallest details first, spread over the whole map, the points of interest last. The client draws ground cover near the camera on any level (ground-cover.ts): tufts of grass, flowers and pebbles read off the ground's colours, never on a road, under water, on a deck or in a building, a quarter as much without a GPU; the simulation never sees it.
Landuse
landuse gives whole tiles over to one use (up to 16 areas, [i, j] and a size like a plateau's, off the spawn apron, the towns, the water and each other); each kind's ground is painted (ground.ts) and dressed (landuse.ts), in plain regions too, and each area has a place, <name> (<kind>_<n> by default):
| Kind | Its ground | What stands on it | Its place |
|---|---|---|---|
farmland | Strips of wheat, crops and earth | A farmyard (a windpump, a trough, bales, a scarecrow), a fence and gate | Its farmyard |
orchard | Mown grass | Rows of fruit trees, beehives | Its middle |
vineyard | Bands of bare earth | Rows of vines on posts, a shed | Its middle |
forest | A dark floor | The biome's trees, dense; stumps, logs, a deer stand | Its middle |
meadow | Long grass | Wild flowers, beehives, a bench | Its middle |
heath | Heather and poor grass | Heather, gorse, boulders, a cairn | Its middle |
quarry | Gravel and cut stone | Boulders, piles of stone, a site cabin, a cement mixer | Its middle |
cemetery | A lawn crossed by paths | A stone wall and gate, rows of graves, cypresses, a shrine | Its gate |
allotments | Beds of earth and crops by paths | Garden sheds, cold frames, compost bins, a fence | Its middle |
campsite | Worn grass | Tents round a campfire, log seats, picnic tables | Its campfire |
park | A lawn crossed by paths | Trees along the paths, flower beds, benches, picnic tables | Its middle |
wetland | Marsh and open water | Reeds, dead trees | Its middle |
The spec
{
"template": "region",
"name": "test-tiles-terrain",
"seed": 3,
"size": [10, 10],
"base": 0,
"biome": "meadow",
"features": [
{ "kind": "hill", "at": [5, 5], "level": 3, "name": "hill" },
{ "kind": "mountain", "at": [7, 7], "level": 3, "radius": 2, "name": "peak" },
{ "kind": "plateau", "at": [2, 6], "size": [2, 2], "level": 2, "name": "plateau" }
],
"props": { "trees": false, "rocks": false }
}| Field | What it is |
|---|---|
template | "region". |
name | The level's: test-<words>, main-<words> or a draft's draft-<id>. |
seed | A whole number from 0 (1 by default): the bumps, the patches of darker grass, the trees and rocks. |
size | [along x, along z], 3 to 16 tiles each. |
base | The land's level inside its rim where no feature says otherwise (0 by default). |
biome | meadow, forest, alpine, farmland, steppe, desert, autumn or coast. |
details | plain (the default) or rich (above). |
landuse | Up to 16 areas: kind, at, size, name (above). |
features | Up to 12 (above): hill, mountain, plateau, valley, lake, volcano, ski. |
towns | Up to 3 (below). |
start | A town's name: the players' four spawn points on the middle block of its first east-west avenue (else its first inner street), two each way, instead of on the spawn apron. |
roads | Up to 8, laid in order: class, from, to, via, name (above). |
props | trees, rocks: whether to strew them (both true by default). |
climate | The weather's odds (Time and weather): the biome's by default, or temperate, another biome's, none (always clear). |
clock | { start, pace }: the time a game on the level starts at (HH:MM) and game minutes per real second, unless the game's rules say otherwise. |
What comes out
npm run level:region -- <spec.json> builds the region without Blender and writes into the kits folder (or --out <dir>) what the town generator writes: the level's own kit (<name>.glb and <name>.foi.json: its ground, one terrain piece colliding as its triangles), its recipe (<name>.recipe.json: the ground, the trees and rocks of the downtown kit, the lakes' and volcanoes' dressing, four spawn points on the apron facing north, or on the avenue of the town start names) and its places (<name>.places.json). It prints the region's map; then npm run level:recipe and npm run level:export as for any recipe:
npm run level:region -- apps/level-editor/assets/kits/test-tiles-terrain.spec.json
npm run level:recipe -- apps/level-editor/assets/kits/test-tiles-terrain.recipe.json --scene test-tiles-terrain
npm run level:exportThe map is the region as text, north up and east to the right, each tile its highest corner's level (A for 10), a feature's tile by its letter (H hill, M mountain, P plateau, V valley, L lake, X volcano, K a ski run's top), water ~, lava *, the apron S:
9 8 7 6 5 4 3 2 1 0 (i, east to the right)
9 0 0 1 1 0 1 1 1 1 0
8 0 2 2 2 2 2 2 2 2 1
7 1 2 M 3 2 2 2 2 2 1
6 1 2 3 3 2 2 2 P 2 1
5 0 2 2 2 H 3 2 2 2 1
4 0 1 2 2 3 3 2 2 1 0
3 0 0 1 2 2 2 2 1 0 0
2 0 0 1 1 2 2 1 1 0 0
1 0 0 0 0 1 1 0 0 0 0
0 0 0 0 0 S S 0 0 0 0The places: tile_<i>_<j> at every tile's middle, on the ground; every feature by its name (or <kind>_<n>) at its peak, floor or middle (a lake's southern shore, a volcano's southern rim, a ski run's top, and its foot <name>_foot); a volcano's crater middle <name>_crater (under the lava, to look at) and, with a flow, the flow's foot <name>_flow; the dressing's <lake>_dock (on the jetty), <lake>_beach and <volcano>_lookout; every road's <name>_start and <name>_end; spawn_<n>. A mission names them as it names a town's. The map marks a road's tiles by its class: : track, - country, + street, = avenue, # highway.
A region with roads, as test-tiles-roads lays them:
{
"template": "region",
"name": "test-tiles-roads",
"size": [12, 10],
"base": 3,
"features": [
{ "kind": "hill", "at": [5, 6], "level": 4, "name": "hill" },
{ "kind": "valley", "at": [8, 5], "radius": 2, "name": "gorge" },
{ "kind": "valley", "at": [8, 6], "radius": 2, "name": "gorge_north" },
{ "kind": "mountain", "at": [3, 7], "level": 3, "radius": 1, "name": "peak" }
],
"roads": [
{
"class": "highway",
"from": "east",
"to": "west",
"via": [
[2, 5],
[9, 5]
],
"name": "highway"
},
{ "class": "country", "from": "spawn", "to": "hill", "name": "country_road" },
{ "class": "track", "from": "highway", "to": "peak", "name": "track" }
]
}A region with water, lava and a ski run (the catalogue's example of the template, template.region):
{
"template": "region",
"name": "test-small-region",
"seed": 3,
"size": [10, 10],
"biome": "alpine",
"features": [
{ "kind": "lake", "at": [2, 5], "size": [2, 2] },
{ "kind": "volcano", "at": [7, 6], "level": 4 },
{ "kind": "mountain", "at": [5, 8], "level": 4, "radius": 2 },
{ "kind": "ski", "at": [5, 8], "to": [5, 5], "name": "piste" }
],
"roads": [
{ "class": "country", "from": "spawn", "to": "lake_1", "name": "lake_road" },
{ "class": "track", "from": "lake_road", "to": "piste" }
]
} 9 8 7 6 5 4 3 2 1 0 (i, east to the right)
9 0 2 2 2 2 2 2 0 0 0
8 2 3 3 3 K 4 2 1 1 1
7 2 4 4 4 4 ~ ~ ~ ~ 1
6 2 4 X * 4 ~ ~ ~ ~ 1
5 2 4 * * : ~ ~ L ~ 1
4 2 4 4 4 : ~ ~ ~ ~ 1
3 2 3 3 3 : 2 - 1 1 1
2 0 2 2 2 : : : 0 0 0
1 0 0 0 0 - - - 0 0 0
0 0 0 0 0 S S 0 0 0 0Towns
A region may hold up to three towns (towns): grid towns built on its tiles, their streets following the land.
{
"name": "old_town",
"at": [3, 4],
"blocks": [4, 4],
"blockTiles": 1,
"districts": [
{ "name": "centre", "theme": "old-town" },
{ "name": "terraces", "blocks": [[3, 3]], "terrace": 3 }
],
"parks": [[1, 1]]
}| Field | What it is |
|---|---|
name | Its name: its places are <name>.<place>, and a road ends at it by it. |
at | Its footprint's first tile. The footprint is blocks × blockTiles + 1 tiles each way: the blocks, and half a tile of verge round its outer streets. |
blocks | Blocks along x and z, 1 to 8. |
blockTiles | Tiles across a block: 1 (64 m) or 2 (128 m, room for a landmark). |
streetWidth, avenues, districts, parks, props, dressing | As a grid-town spec has them (no compounds; dressing lived-in for bus stops, car parks, yards and street furniture, see Levels). A district may have a terrace: the level its blocks are all levelled at. |
The town's street lines run through the middles of its tiles, so every junction stands at the land's height there and every street climbs at a steady grade from one junction to the next: level across a junction (its crossing street, its pavements and its corners' kerbs), then a grade of about 9 % for a level a block, eased in and out. Inside a town the land climbs a level a tile at most, two only under a hill or valley marked "steep": true (about 14 to 18 % between the junctions); never on the town's outermost tiles (its ring street and the roads coming in) nor along an avenue. Every vehicle class pulls away on 18 % and climbs it; a car driven through a hilly town much above its 50 km/h leaps the crests where a street levels out into a junction.
Its buildings stand on pads, level with the pavement at their doors: where the ground falls away under one, a plinth wall shows under its front; where it rises, the cut hides behind its walls. A building whose ground would fall more than 3.5 m or rise more than 4 m under it is not built there (the next one in the mix is tried). A park's round square is level too, its fountain on it. A terraced district sits flat at its level, its neighbours sloping to it (a street never has two heights). The ground between the streets is a smooth surface held at the pavements and, on the footprint's outline, at the region's own ground, vertex for vertex.
What a town may not do is an issue at its path: a footprint that reaches the rim, the spawn apron, another town, water or lava, a mountain's or a volcano's flanks or a ski run (towns[0].at); a terrace the land cannot reach at a level a tile (towns[0].districts[1].terrace); a name another feature, road or town has (towns[0].name). A road of the region ends at a town by its name, at the free socket nearest its other end: the middle of an outer edge of the footprint where a street line comes out (one road per socket; the ring's corners aside); the town builds the street on in from there. The map marks the town's tiles T.
Towns are built by the town generator (Blender, assets/blender/levels/generate.py --relief, relief.py), so a region with towns needs Blender where it is built: level:region finds it on this machine, the platform builds it on its generator worker. The test level is test-tiles-town (E2E-429 to 431), its town lived-in.
The bundled regions are test levels: test-tiles-terrain, test-tiles-roads, test-tiles-tunnel, test-tiles-town and test-plots. None has a lake, a volcano, a ski run or a lighthouse; a creator's region can have them all.
Seeing them
The kit gallery, /?kit-gallery=terrain (or =features, =biomes, =landuse, =roads, =nature) on the web client with no server, lays out the seven shapes a tile each, every feature on a small region of its own (the lake's water and the crater's lava with them), a mountain in each biome in its rich tones, each landuse kind's ground on a small region of its own, a straight stretch of each road class, built by the same @foi/catalogue code as a region, beside every building and prop of the kits a town is built of.
On the platform
A region is a level spec like a town (template: "region", foi://schemas/level-spec, the catalogue's template.region and tile.* entries, this page as foi://guide/tiles). level_spec_set (PUT /drafts/:id/spec) solves it at once: a region that cannot be built is refused with every problem's path under spec, one that can comes back with its map. draft_build then builds it: on the generator worker when there is one, else in the API's own process, without Blender (apps/worker's generateRegion; Blender only renders the preview, when it is there). A region with towns needs Blender for them: the worker, or the API with Blender installed where it runs.
Tests that tiles combine
Rather than every pair of tiles, the tests hold what makes any pair meet:
- every seam of a region is the line between its two corners (
packages/catalogue/src/region/region.test.ts); - every tile is one of the shapes above, turned (the same file), and twenty regions of random features are each built consistent or refused with a path;
- a car crosses five seams up a hill with its wheels down and no jolt, a person walks a mountain's steep flank both ways (
packages/sim/src/terrain-tiles.test.ts; E2E-422 and 423 ontest-tiles-terrain); - every tile of the test region is reachable on foot from the spawns (
packages/world/src/levels.test.ts); - every road reaches its end through the tiles it must pass, never climbs faster than its class, crosses another at that road's height and ends on the one it joins; the ground under a road is the road's height; the gorge is bridged (
packages/catalogue/src/region/roads.test.ts); - a car drives the highway over the bridge, its wheels on the deck (
packages/sim/src/terrain-tiles.test.ts; E2E-424), and the country road across the highway at a flat junction (E2E-425), ontest-tiles-roads, whose roads all lie on what carries them and meet in one road graph.