Civ5Map File Format

MouseyPounds

Prince
Joined
Nov 8, 2010
Messages
417
Location
Maryland, USA
What follows is a partially-complete outline of the Civ5Map file format. Most of the heavy-lifting on this was done by dannythefool for his Civ5 Replay reader. While trying to update that script for the latest patch, I did some further investigating and decided to post this reference. My interest is mostly in the map itself, so information on the scenario data is almost entirely missing from the current version of this guide.

Civ5Map File Format

Map Header

byte -- Type/version indicator. See Notes below.
int -- Map Width
int -- Map Height
byte -- Possibly number of players for scenario.
int -- Unknown; seems to be a world wrap indicator (1 if wrap, 0 if no wrap)
int -- Length of Terrain type list
int -- Length of 1st Feature type list
int -- Length of 2nd Feature type list
int -- Length of Resource type list
int -- Unknown
int -- Length of Map Name string
int -- Length of Description string
string[] -- Terrain type list
string[] -- 1st Feature type list
string[] -- 2nd Feature type list
string[] -- Resource type list
string -- Map Name string
string -- Description string
int -- Length of String3 (only present in version xB or later)
string -- String3 (only present in version xB or later)

Map Data
Map data is just a list of plots, where a plot is an array of 8 bytes. It starts at plot (0,0), continues along the x-axis until the row is done, then moves on to (0,1), etc. So a useful way to read it is to loop the y values from 0 to Height-1 and inside that loop the x values from 0 to Width-1; then you can simply read the next 8 bytes to get the info for plot (x,y) and do whatever you need to with it.

A plot array looks like this:
byte 0 -- Terrain type ID (index into list of Terrain types read from header)
byte 1 -- Resource type ID; 0xFF if none
byte 2 -- 1st Feature type ID; 0xFF if none
byte 3 -- River indicator (non-zero if tile borders a river; actual value probably indicates direction)
byte 4 -- Elevation (0 = Flat, 1 = Hill, 2 = Mountain)
byte 5 -- Unknown (possibly related to continent art style)
byte 6 -- 2nd Feature type ID; 0xFF if none
byte 7 -- Unknown

Scenario Header and Data
If there is any scenario data present, it will appear after the map. I haven't really needed to use this part of the file, so info here is more sparse.

84 unknown bytes
int -- Length of Improvement type list
int -- Length of Unit type list
int -- Length of Tech type list
int -- Length of Policy type list
int -- Length of Building type list
int -- Length of Promotion type list
20 unknown bytes
string[] -- Improvement type list
string[] -- Unit type list
string[] -- Tech type list
string[] -- Policy type list
string[] -- Building type list
string[] -- Promotion type list

That's about where I lose track of things. The next section seems to relate to player data but from here on I just didn't have the time or interest to try and work out what everything is in this part of the file.

Notes:
  • The first byte (which I call a type/version indicator) seems to have a high nybble of 0 if the map is just a bare terrain map and a high nybble of 8 if the map also contains scenario information -- i.e. cities, units, etc. The low nybble was xA for older maps (prior to the December patch) and is xB for maps exported from the current game (patch 1.0.1.221).
  • All integers are 4-byte little Endian; I generally treat them all as signed.
  • All strings are null-terminated.
  • The "type lists" are blocks of known size which contain several null-terminated strings. For example, if I use a period to represent the null byte, the Terrain type list might look like this:
    Code:
    TERRAIN_GRASS.TERRAIN_PLAINS.TERRAIN_DESERT.TERRAIN_TUNDRA.TERRAIN_SNOW.TERRAIN_COAST.TERRAIN_OCEAN.
    These blocks can be read en masse and then split on the nulls into an array of type names.
  • The int/string combination for String3 was apparently added for version xB maps as it is not present in any version xA maps that I've looked at.
  • Plots only seem to have 1 of the 2 feature types present. For exported maps, if a plot has a "normal" feature (forest, jungle, flood plain) it'll be the first feature; if instead it has a Natural Wonder feature, it'll be the second feature.
 
I am using this reference in my project and it is very helpful. I just wanted to add to this what I have found out about

int -- Unknown; seems to be a world wrap indicator (1 if wrap, 0 if no wrap)

Actually I think this is a bitmask for misc. settings. In integer values this is what it refers to:

first bit : World wrap on/off
second bit : Randomize resources
third bit : Randomize goodies

So 7 is all on, 0 is all of and 5 is goodies and world wrap and so on...

Edit 1: Figured out also that byte 5 is actually continent setting. Civ5 WorldBuilder has settings that allow you to set a continent. These are the values :

// tile_buffer[5] unknown probably continents
// 0 = nothing
// 1 Americas
// 2 Asia
// 3 Africa
// 4 Europe

But when I painted a map (using default values for four corners generation), it appeared upside down. That is first all was Asia, which gave me a value 2 for the whole map except oceans and coasts. Then I changed one corner to America and one to Europe. Those were the top corners, but in my output I had bottom corners reflect the change. So I'm thinking that the map actually starts at the width-1, height-1 and ends up at 0,0. It shouldn't be hard to flip those, just thought you should know. My project will at least definitely have a working Civ5Map reader and Civ5Map writer if anyone wants a copy when I'm finished.
 
Something new:
1. Version can be xC in the latest version of WorldBuilder.

2. Mod Data Part
in front of
string -- Map Name string
string -- Description string
there is a part storing Mod Data, which seems like some opcode. So I cannot guess how to count the length of this part.
And Unknown field is also related with this.
int -- Length of Resource type list
int -- Unknown
int -- Length of Map Name string

3. After Building Type List, there is a part contains some scenario game options. but not simply separated by nil, but with a one-byte-long length in front of each string.

4. Map Width and Map Height is UInt32, from decompiling the world builder.

5. There are some xFF after all the data. I get two situation of its length, Width*Height*2 or Width*Height*8.
 
Does any one know how the river indicator is computed? I find the lowest 3 bits means three directions(left down, right down and right). but the higher bits may also be set. I cannot guess the rule.
 
I got it!
int -- Length of Resource type list
int -- Unknown
int -- Length of Map Name string
The int field Unknown is the length of ModData Part.
my summary:
MapHeader
bit(4) -- has scenario data? x8 means has, 0 means not.
bit(4) -- File format version indicator. (xC, xB, xA)
uint32 -- Map Width
uint32 -- Map Height
byte -- number of players for scenario.
bit(5) -- ?
bit bool(1) -- random goodies
bit bool(1) -- random resource
bit bool(1) -- world wrap
bit(24) -- ?
int -- Length of Terrain type list
int -- Length of 1st Feature type list
int -- Length of 2nd Feature type list
int -- Length of Resource type list
int -- Length of Mod Data Part
int -- Length of Map Name string
int -- Length of Description string
string[] -- Terrain type list
string[] -- 1st Feature type list
string[] -- 2nd Feature type list
string[] -- Resource type list
text -- Mod Data Part (seems to be some compiled lua, the end of it is usually some string-like data)
string -- Map Name string(UTF8?)
string -- Description string(UTF8?)
uint32 -- Length of String3 (only present in version xB or later)
text -- String3 (only present in version xB or later), always 64bytes of 0?

MapData
byte(8) * width * height -- the cells is ordered like (0,0) (1,0) (width,0) (0,1) (1,1)...(width, height)
byte 0 -- Terrain type ID (index into list of Terrain types read from header)
byte 1 -- Resource type ID; 0xFF if none
byte 2 -- 1st Feature type ID; 0xFF if none
byte 3 -- River indicator
0 means no river.
The low 3 bits means a border is river. a river always belongs to its north or west plot.
4 -- south west border
2 -- south east border
1 -- east border
The high 5 bits, unknown.
byte 4 -- Elevation (0 = Flat, 1 = Hill, 2 = Mountain)
byte 5 -- Unknown (possibly related to continent art style)
byte 6 -- 2nd Feature type ID; 0xFF if none
byte 7 -- Unknown, Usually 0.

Scenario Header
72bytes -- GameSpeed Option, Null-terminated string
int32 -- MaxTurn, usually 0
int32 -- 0
int32 -- FFFFF060, the age start the game, which is B.C.4000
int8 -- count of player
int8 -- count of city states
int8 -- count of players+city states
int8 -- 0
uint32 -- Length of Improvement type list
uint32 -- Length of Unit type list
uint32 -- Length of Tech type list
uint32 -- Length of Policy type list
uint32 -- Length of Building type list
uint32 -- Length of Promotion type list
uint32 -- ?
uint32 -- ?
uint32 -- ?
uint32 -- Length of Victory Options Part(it is a different string list. each string has a byte of its length, like shortstring of Pascal/Delphi)
uint32 -- Length of Some Game Options(the same format with above item)
20 unknown bytes
string[] -- Improvement type list
string[] -- Unit type list
string[] -- Tech type list
string[] -- Policy type list
string[] -- Building type list
string[] -- Promotion type list

Player Scenario Data
i cannot find how long this part is.....the only thing I can find is that it will be 0 byte long when there is no player or city state.

Map Scenario Data
byte(8) * width * height -- usually filled with 0xFF
byte 6 -- road, 0 for road, 1 for railway, 0xFF for no road.
 
Last edited:
Further Advance from decompiling world builder:
Byte 3 of MapData -- Flag, Bit Masked Byte, the high 5 bits is something, the low 3 bits is river indicator.
Byte 5 of MapData -- FeatureB, which is natural wonder
Byte 7 of MapData -- Resource Amount
 
Top Bottom