Game development

How is a strategy game's world map made?

For MKA Engine we built a 27,357-location world map of 1337 from real data: how terrain, rivers, straits, population and location borders were made.

Contents

Anyone who plays grand strategy has spent hours staring at the map. Armies march across it, taxes are collected from it, a river slows an attack, a strait links two continents. In this genre the map is not a background picture. It is the game board.

For MKA Engine we built that board ourselves from real-world data. This post explains how, starting from a player's point of view and going down to the details a developer would ask about. We picked 1337 as the first test year. Every number below was measured on this map.

  • 27,357 locations 21,622 land, 5,735 sea and lake
  • 16,384 × 8,192 pixels about 1.7 km per pixel at 45 degrees latitude
  • 410 million population estimate for 1337 spread over 21,622 land locations
  • 3.4 s loading the map into the engine two builds byte for byte identical
The 1337 world map

What does the map do in the game?

Think of the map as a chessboard whose squares are not equal. Every location is a square on the board. It has a terrain (plains, hills, mountains), a vegetation (forest, farmland, steppe), a climate and a population. An army marches from one location to a neighbour. If the border between them crosses a river, the march gets harder. If a narrow sea separates two pieces of land, the army can cross the strait.

To the engine, the map is a graph. Nodes are locations, edges are neighbourships. An edge can carry extra information: a river crossing, a strait, a canal or a river navigable by ship. The engine finds paths, measures distances and builds supply lines on this graph. How much a terrain penalises an attacker is up to the game; the engine does not know the word "mountain", it only carries the terrain types the game defines.

Real data first, but only data we may use

The first rule was simple: every dataset in the map must come with a licence that allows use in a commercial game. We accepted public domain, CC0 and CC BY data. We dropped data that forbids commercial use (NC) or forces derivatives to be shared under the same licence from the start. That ruled out some well-known sources; the WorldClim climate data and OpenStreetMap coastlines, for example, did not pass.

LayerSourceLicence
Elevation and sea depthNOAA ETOPO 2022CC0
Coasts, lakes, glaciers, present-day borders, sea namesNatural EarthPublic domain
RiversHydroRIVERS (HydroSHEDS)HydroSHEDS licence; derivative only
Large lakesHydroLAKESCC BY 4.0
Natural vegetationRESOLVE Ecoregions 2017CC BY 4.0
Farmland cleared by 1337KK10 (Kaplan and Krumhardt)CC BY 3.0
Climate zoneKoppen-Geiger (Beck et al. 2023)CC BY 4.0
Country populationMaddison Project 2023CC BY 4.0
Historical city populationChandler (Reba et al. 2016), BuringhCC BY 4.0, CC0
Place namesGeoNamesCC BY 4.0
Data in the map

Every file is recorded with a fingerprint pinned on the day it was downloaded. If a source file changes, the pipeline notices and stops.

Laying the globe flat

There is no perfect way to lay a sphere flat; every projection distorts something. We chose the Gall stereographic projection. Its meridians are straight and evenly spaced, so the east edge of the map joins the west edge without a seam, and a ship sailing across the Pacific does not get stuck at the map border. Around 45 degrees latitude, which covers most of Europe, Anatolia and China, the scale is true. Towards the poles it stretches less than the common plain latitude-longitude map.

The map is 16,384 × 8,192 pixels and covers roughly 75 degrees north to 56 degrees south. Cape Horn is inside; Antarctica and Svalbard are not.

A detail for developers: we build every layer on a plain latitude-longitude grid first and apply the projection as the very last step. If we want another projection, only that last step runs again. The engine does not measure distance on the flat map either. Each location comes with its position on the sphere in kilometres, so the distance between two locations stays close to reality at every latitude.

Terrain: plains, hills, mountains

You cannot tell a mountain from a plain by elevation alone. The Konya Plain in central Anatolia sits 1,000 metres above sea level and is completely flat. So for every point we look at the difference between the highest and lowest ground around it. A small difference means plains, a medium one hills, a large one mountains. High but flat ground becomes a plateau.

Vegetation comes from two layers. Natural vegetation comes from present-day ecoregions: forest, steppe, desert, tundra. Then we look at KK10, a dataset that estimates, year by year, how much forest people had cleared for fields. Where most of the land was cleared by 1337 the location becomes farmland; where about half was cleared it becomes woods. The same method will give a different answer for an 1836 map.

Vegetation of land locations (1337) (locations)

02,0004,0006,0008,0007,6664,7183,2272,1001,9661,471432FarmlandSteppe and grasslandWoodsForestTropical forestDesertTundra
Vegetation of land locations (1337)
LabelLocations
Farmland7,666
Steppe and grassland4,718
Woods3,227
Forest2,100
Tropical forest1,966
Desert1,471
Tundra432
Source: MKA Engine 1337 map package, 21,622 land locations

Some locations cannot be entered at all: glaciers, mountains whose average height is above 5,000 metres, and deserts where almost nobody lives. The 1337 map has 674 of them. They are the grey areas in the cover image.

Cutting the map into locations

This is the hardest part. Imagine cutting a cake into slices when you cannot put the knife wherever you like. The slices should be roughly equal, each must stay in one piece, and the cuts should follow natural lines where possible: rivers, ridges, coasts.

The method works like this:

  1. First the centres of the locations are chosen. Every known city with more than 10,000 people in 1337 becomes the centre of its own location. The remaining centres are spread by population: small locations where many people live, large ones where few do.
  2. A flood starts from every centre and spreads like water (this is called "watershed" segmentation). Rivers, ridges and coasts act like uphill slopes for the flood, so neighbouring floods tend to meet on those lines, and the borders settle there.
  3. Centres that are not cities are moved to the middle of their location twice and the flood runs again. This makes locations rounder.
  4. Leftover crumbs join a neighbour, and every location is checked to be a single piece.

The sea uses the same method with a different target size. Sea locations come out small along coasts and straits and large on the open ocean. In the image you can see the small sea locations around the Bosphorus and the Dardanelles.

MeasureResult
Land locations21,622
Sea and lake locations5,735
Median land location area2,313 km²
Land border on a river28.8%
Land border on a ridge20.3%
Land border on a coast15.1%
Locations in more than one piece0
Partition measurements

We ran the partition twice from the same data; the two outputs were byte for byte identical.

From locations to provinces, regions and subcontinents

A player does not manage 27 thousand locations one by one. Locations are grouped, and groups join larger groups. Our map has four levels: provinces of about five locations each (5,181), areas (912), regions (131) and subcontinents (19).

Groups are built by merging neighbouring locations step by step. Each step picks the best pair of neighbours, aiming for compact groups of similar size. Two locations in different climate zones, or on two sides of a present-day country border, merge less easily. Land and sea never mix at any level.

Every location and every group has a name and a permanent key: istanbul, canakkale, kobenhaven. Names come from settlement names in GeoNames. This matters to modders: when the map is rebuilt, keys are kept. In our test, even when location centres shifted a little, at least 95% of the keys stayed in place. A key that was used once is never given to another place, so an old mod does not change the wrong location.

Rivers, straits and canals

Rivers come from HydroRIVERS. Every land border that crosses a big enough river is marked as a "river crossing". We also picked, one by one, 27 major rivers that carried ship traffic in 1337: the Danube, Rhine, Volga, Nile, Euphrates, Tigris, Yangtze, Ganges and others. Along their courses 3,036 land borders were marked as "waterways".

We named some straits ourselves: the Bosphorus, the Dardanelles, Gibraltar, the Oresund and the Bab-el-Mandeb. The pipeline finds the rest: a water gap shorter than 35 kilometres between two separate pieces of land is a strait candidate. For every pair of landmasses only the shortest gap is kept. That rule gave 1,168 more straits. Suez and Panama are marked as "canals". Neither existed in 1337; the game will decide when they open.

How many people lived in 1337?

Nobody knows exactly; historians have estimates. This is how we went about it:

  1. We took country totals from the Maddison Project. Maddison has no figure for 134 countries. We estimated those from the population density of countries with known figures in the same subregion and the same climate zone, and marked them as estimates in the record.
  2. We placed known cities from the Chandler and Buringh collections.
  3. We spread the remaining rural population over land locations. Farmland, plains, riverbanks and coasts attract more people; mountains, deserts and tundra fewer.

The result: a world population of about 410 million in 1337. McEvedy and Jones's well-known atlas of historical population gives 443 million for 1340; our estimate is 7.4% below it. We used the atlas only for comparison; it is not in the map.

Same data, same map

In a multiplayer strategy game every player's computer calculates the world on its own. So the map has to be the same for everyone too. If a location border moved by one pixel on one computer, a few game years later two players could be playing in different worlds. We covered this in detail in the Multiplayer and consistency diary.

That is why every step of the map can be repeated. Every choice that looks random comes from a fixed seed. The map package enters the engine through the bsm map build tool. It renumbers the locations so that places close together on screen are also close together in memory, extracts neighbourships and border lengths, and writes the tables the engine reads. For the full map this takes 3.4 seconds. We ran the tool twice; the two outputs were byte for byte identical.

On screen: Godot

To see the map on screen we wrote a small viewer in Godot 4.7. The idea is the one most grand strategy games use: every pixel of the map is a texture value holding the number of the location it belongs to. For every pixel the graphics card looks up that number and takes the location's colour from a small colour table. When a location's owner or the map mode changes, only the colour table changes; the roughly 270 MB map texture is not touched. Borders are drawn the same way: where a pixel's neighbour has a different number, there is a border.

MeasureResult
Loading the map0.5 seconds
Graphics memory280 MB
Frame time, whole world in view5.2 to 5.7 ms
Frame time, zoomed in1.3 to 1.4 ms
Viewer measurements

The measurements were taken on a computer without a separate graphics card, on the AMD Radeon graphics built into the processor. The computer was busy with other work during the measurement. This viewer is not a game front end; it is a tool for checking the map.

What is missing?

The map today is a test, and we are not hiding its gaps:

  • Impassable deserts are too wide. The Sahara, Arabia and inner Australia are almost entirely grey. In reality caravans crossed these deserts in 1337. We will tune the threshold.
  • The Caspian Sea and the Siberian lakes join the Mediterranean region, the nearest sea region. Lakes should get regions of their own.
  • There are no political borders. We found no historical border data for 1337 that allows commercial use. Countries and their borders will be built by hand as game content.
  • Weather is not in the map. Seasons and weather change over time. Instead of baking them into a fixed map, we leave them to the engine. The map only carries each location's climate zone.
  • There is no 1836 map yet. The method is ready; the second year needs its own data and a new run.

There is no playable game yet. This map was made to test whether the engine can carry a world at full scale, and it passed: the 27-thousand-location world loads into the engine in seconds and draws smoothly on screen.

You can follow the overall state of MKA Engine on the MKA Engine page, and read why and how the engine is being written in The road to a game engine.

Sources

  • NOAA National Centers for Environmental Information (2022): ETOPO 2022 Global Relief Model (30 arc-second version), doi:10.25921/fd45-gt74.
  • Natural Earth (naturalearthdata.com), 10m physical and cultural layers.
  • Lehner, B. and Grill, G. (2013): Global river hydrography and network routing: baseline data and new approaches to study the world's large river systems. Hydrological Processes 27(15). HydroRIVERS, under the HydroSHEDS licence.
  • Messager, M. L. et al. (2016): Estimating the volume and age of water stored in global lakes using a geo-statistical approach. Nature Communications 7:13603 (HydroLAKES).
  • Dinerstein, E. et al. (2017): An Ecoregion-Based Approach to Protecting Half the Terrestrial Realm. BioScience 67(6) (RESOLVE Ecoregions 2017).
  • Kaplan, J. O. and Krumhardt, K. M. (2011): KK10 historical land use, PANGAEA, doi:10.1594/PANGAEA.871369.
  • Beck, H. E. et al. (2023): High-resolution (1 km) Koppen-Geiger maps for 1901-2099 based on constrained CMIP6 projections. Scientific Data 10:724.
  • Bolt, J. and van Zanden, J. L. (2024): Maddison Project Database 2023.
  • Reba, M., Reitsma, F. and Seto, K. C. (2016): Spatializing 6,000 years of global urbanization from 3700 BC to AD 2000. Scientific Data 3:160034 (Chandler data).
  • Buringh, E.: European urban population, 700-2000, DANS, doi:10.17026/dans-xzy-u62q.
  • GeoNames (geonames.org), cities1000, download of 14 October 2026.
  • McEvedy, C. and Jones, R. (1978): Atlas of World Population History (comparison only).

Sources and related docs

You may also like