MouseyPounds
Prince
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:
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.
- 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.