Data model - Azgaar/Fantasy-Map-Generator GitHub Wiki
FMG data model is poorly defined, inconsistent and not documented in the codebase. This page is the first and the only attempt to document it. Once everything is documented, it can be used for building a new consistent model. Please note the current document reflect the object model as is, so with all its quirks. The model we want to get is covered separately.
FMG exposes all its data into the global namespace. The global namespace is getting polluted and it can cause conflicts with 3rd party extensions. Meanwhile it simplifies debugging and allows users to run custom JS code in dev console to alter the tool behavior.
Basic objects
FMG has two meta-objects storing most of the map data:
grid
contains map data before repackingpack
contains map data after repacking
Repacking is a process of amending an initial voronoi diagram, that is based on a jittered square grid of points, into a voronoi diagram optimized for the current landmass (see my old blog post for the details). So the pack
object is used for most of the data, but data optimized for square grid is available only via the grid
object.
Voronoi data
Both grid
and pack
objects include data representing voronoi diagrams and their inner connections. Both initial and repacked voronoi can be build from the initial set of points, so this data is stored in memory only. It does not included into the .map file and getting calculated on map load.
Grid object
-
grid.cellsDesired
:number
- initial count of cells/points requested for map creation. Used to definespacing
and place points on a jittered square grid, hence the object name. Actual number of cells is defined by the number points able to place on a square grid. DefaultcellsDesired
is 10 000, maximum - 100 000, minimal - 1 000 -
grid.spacing
:number
- spacing between points before jittering -
grid.cellsY
:number
- number of cells in column -
grid.cellsX
:number
- number of cells in row -
grid.points
:number[][]
- coordinates[x, y]
based on jittered square grid. Numbers rounded to 2 decimals -
grid.boundary
:number[][]
- off-canvas points coordinates used to cut the diagram approximately by canvas edges. Integers -
grid.cells
:{}
- cells data object, including voronoi data: -
grid.cells.i
:number[]
- cell indexesUint16Array
orUint32Array
(depending on cells number)
-
grid.cells.c
:number[][]
- indexes of cells adjacent to each cell (neighboring cells)
-
grid.cells.v
:number[][]
- indexes of vertices of each cell
-
grid.cells.b
:number[]
- indicates if cell borders map edge, 1 iftrue
, 0 iffalse
. Integers, not Boolean
-
grid.vertices
:{}
- vertices data object, contains only voronoi data: -
grid.vertices.p
:number[][]
- vertices coordinates[x, y]
, integers
-
grid.vertices.c
:number[][]
- indexes of cells adjacent to each vertex, each vertex has 3 adjacent cells
-
grid.vertices.v
:number[][]
- indexes of vertices adjacent to each vertex. Most vertices have 3 neighboring vertices, bordering vertices has only 2, while the third is still added to the data as-1
Pack object
-
pack.cells
:{}
- cells data object, including voronoi data: -
pack.cells.i
:number[]
- cell indexesUint16Array
orUint32Array
(depending on cells number)
-
pack.cells.p
:number[][]
- cells coordinates[x, y]
after repacking. Numbers rounded to 2 decimals
-
pack.cells.c
:number[][]
- indexes of cells adjacent to each cell (neighboring cells)
-
pack.cells.v
:number[][]
- indexes of vertices of each cell
-
pack.cells.b
:number[]
- indicator whether the cell borders the map edge, 1 iftrue
, 0 iffalse
. Integers, not Boolean
-
pack.cells.g
:number[]
- indexes of a source cell ingrid
.Uint16Array
orUint32Array
. The only way to find correctgrid
cell parent forpack
cells
-
pack.vertices
:{}
- vertices data object, contains only voronoi data: -
pack.vertices.p
:number[][]
- vertices coordinates[x, y]
, integers
-
pack.vertices.c
:number[][]
- indexes of cells adjacent to each vertex, each vertex has 3 adjacent cells
-
pack.vertices.v
:number[][]
- indexes of vertices adjacent to each vertex. Most vertices have 3 neighboring vertices, bordering vertices has only 2, while the third is still added to the data as-1
Features data
Features represent separate locked areas like islands, lakes and oceans.
Grid object
grid.features
:object[]
- array containing objects for all enclosed entities of original graph: islands, lakes and oceans. Feature object structure:-
i
:number
- feature id starting from1
-
land
:boolean
-true
if feature is land (height >=20
)
-
border
:boolean
-true
if feature touches map border (used to separate lakes from oceans)
-
type
:string
- feature type, can beocean
,island
or `lake
Pack object
pack.features
:object[]
- array containing objects for all enclosed entities of repacked graph: islands, lakes and oceans. Note: element 0 has no data. Stored in .map file. Feature object structure:-
i
:number
- feature id starting from1
-
land
:boolean
-true
if feature is land (height >=20
)
-
border
:boolean
-true
if feature touches map border (used to separate lakes from oceans)
-
type
:string
- feature type, can beocean
,island
orlake
-
group
:string
: feature subtype, depends on type. Subtype for ocean isocean
; for land it iscontinent
,island
,isle
orlake_island
; for lake it isfreshwater
,salt
,dry
,sinkhole
orlava
-
cells
:number
- number of cells in feature
-
firstCell
:number
- index of the first (top left) cell in feature
-
vertices
:number[]
- indexes of vertices around the feature (perimetric vertices) **name
:string
- name, available forlake
type only
Specific cells data
World data is mainly stored in typed arrays within cells
object in both grid
and pack
.
Grid object
grid.cells.h
:number[]
- cells elevation in[0, 100]
range, where20
is the minimal land elevation.Uint8Array
grid.cells.f
:number[]
- indexes of feature.Uint16Array
orUint32Array
(depending on cells number)grid.cells.t
:number[]
- distance field from water level.1, 2, ...
- land cells,-1, -2, ...
- water cells,0
- unmarked cell.Uint8Array
grid.cells.temp
:number[]
- cells temperature in Celsius.Uint8Array
grid.cells.prec
:number[]
- cells precipitation in unspecified scale.Uint8Array
Pack object
pack.cells.h
:number[]
- cells elevation in[0, 100]
range, where20
is the minimal land elevation.Uint8Array
pack.cells.f
:number[]
- indexes of feature.Uint16Array
orUint32Array
(depending on cells number)pack.cells.t
:number[]
- distance field.1, 2, ...
- land cells,-1, -2, ...
- water cells,0
- unmarked cell.Uint8Array
pack.cells.s
:number[]
- cells score. Scoring is used to define best cells to place a burg.Uint16Array
pack.cells.biome
:number[]
- cells biome index.Uint8Array
pack.cells.burg
:number[]
- cells burg index.Uint16Array
pack.cells.culture
:number[]
- cells culture index.Uint16Array
pack.cells.state
:number[]
- cells state index.Uint16Array
pack.cells.province
:number[]
- cells province index.Uint16Array
pack.cells.religion
:number[]
- cells religion index.Uint16Array
pack.cells.area
:number[]
- cells area in pixels.Uint16Array
pack.cells.pop
:number[]
- cells population in population points (1 point = 1000 people by default).Float32Array
, not rounded to not lose population of high population ratepack.cells.r
:number[]
- cells river index.Uint16Array
pack.cells.fl
:number[]
- cells flux amount. Defines how much water flow through the cell. Use to get rivers data and score cells.Uint16Array
pack.cells.conf
:number[]
- cells flux amount in confluences. Confluences are cells where rivers meet each other.Uint16Array
pack.cells.harbor
:number[]
- cells harbor score. Shows how many water cells are adjacent to the cell. Used for scoring.Uint8Array
pack.cells.haven
:number[]
- cells haven cells index. Each coastal cell has haven cells defined for correct routes building.Uint16Array
orUint32Array
(depending on cells number)pack.cells.routes
:object
- cells connections via routes. E.g.pack.cells.routes[8] = {9: 306, 10: 306}
shows that cell8
has two route connections - with cell9
via route306
and with cell10
by route306
pack.cells.q
:object
- quadtree used for fast closest cell detection
Secondary data
Secondary data available as a part of the pack
object.
Cultures
Cultures (races, language zones) data is stored as an array of objects with strict element order. Element 0 is reserved by the wildlands culture. If culture is removed, the element is not getting removed, but instead a removed
attribute is added. Object structure:
i
:number
- culture id, always equal to the array indexbase
:number
- nameBase id, name base is used for names generationname
:string
- culture nameorigins
:number[]
- ids of origin cultures. Used to render cultures tree to show cultures evolution. The first array member is main link, other - supporting out-of-tree linksshield
:string
- shield type. Used for emblems renderingcenter
:number
- cell id of culture center (initial cell)code
:string
- culture name abbreviation. Used to render cultures treecolor
:string
- culture color in hex (e.g.#45ff12
) or link to hatching pattern (e.g.url(#hatch7)
)expansionism
:number
- culture growth multiplier. Used mainly during cultures generation to spread cultures not uniformlytype
:string
- culture type, see culture typesarea
:number
- culture area in pixelscells
:number
- number of cells assigned to culturerural
:number
- rural (non-burg) population of cells assigned to culture. In population pointsurban
:number
- urban (burg) population of cells assigned to culture. In population pointslock
:boolean
-true
if culture is locked (not affected by regeneration)removed
:boolean
-true
if culture is removed
Burgs
Burgs (settlements) data is stored as an array of objects with strict element order. Element 0 is an empty object. If burg is removed, the element is not getting removed, but instead a removed
attribute is added. Object structure:
i
:number
- burg id, always equal to the array indexname
:string
- burg namecell
:number
- burg cell id. One cell can have only one burgx
:number
- x axis coordinate, rounded to two decimalsy
:number
- y axis coordinate, rounded to two decimalsculture
:number
- burg culture idstate
:number
- burg state idfeature
:number
- burg feature id (id of a landmass)population
:number
- burg population in population pointstype
:string
- burg type, see culture typescoa
:object
- emblem object, data model is the same as in Armoria and covered in API documentation. The only additional fields are optionalsize
:number
,x
:number
andy
:number
that controls the emblem position on the map (if it's not default). If emblem is loaded by user, then the value is{ custom: true }
and cannot be displayed in ArmoriaMFCG
:number
- burg seed in Medieval Fantasy City Generator (MFCG). If not provided, seed is combined from map seed and burg idlink
:string
- custom link to burg in MFCG.MFCG
seed is not used if link is providedcapital
:number
-1
if burg is a capital,0
if not (each state has only 1 capital)port
:number
- if burg is not a port, then0
, otherwise feature id of the water body the burg stands oncitadel
:number
-1
if burg has a castle,0
if not. Used for MFCGplaza
:number
-1
if burg has a marketplace,0
if not. Used for MFCGshanty
:number
-1
if burg has a shanty town,0
if not. Used for MFCGtemple
:number
-1
if burg has a temple,0
if not. Used for MFCGwalls
:number
-1
if burg has walls,0
if not. Used for MFCGlock
:boolean
-true
if burg is locked (not affected by regeneration)removed
:boolean
-true
if burg is removed
States
States (countries) data is stored as an array of objects with strict element order. Element 0 is reserved for neutrals
. If state is removed, the element is not getting removed, but instead a removed
attribute is added. Object structure:
i
:number
- state id, always equal to the array indexname
:string
- short (proper) form of the state nameform
:string
- state form type. Available types areMonarchy
,Republic
,Theocracy
,Union
, andAnarchy
formName
:string
- string form name, used to get statefullName
fullName
:string
- full state name. Combination of the proper name and stateformName
color
:string
- state color in hex (e.g.#45ff12
) or link to hatching pattern (e.g.url(#hatch7)
)center
:number
- cell id of state center (initial cell)pole
:number[]
- state pole of inaccessibility (visual center) coordinates, see the concept descriptionculture
:number
- state culture id (equals to initial cell culture)type
:string
- state type, see [culture types](https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Culture types)expansionism
:number
- state growth multiplier. Used mainly during state generation to spread states not uniformlyarea
:number
- state area in pixelsburgs
:number
- number of burgs within the statecells
:number
- number of cells within the staterural
:number
- rural (non-burg) population of state cells. In population pointsurban
:number
- urban (burg) population of state cells. In population pointsneighbors
:number[]
- ids of neighboring (bordering by land) statesprovinces
:number[]
- ids of state provincesdiplomacy
:string[]
- diplomatic relations status for all states. 'x' for self and neutrals. Element 0 (neutrals)diplomacy
is used differently and contains wars story asstring[][]
campaigns
:object[]
- wars the state participated in. The was is defined asstart
:number
(year),end
:number
(year),name
:string
alert
:number
- state war alert, see military forces pagemilitary
:Regiment[]
- list of state regiments, see military forces pagecoa
:object
- emblem object, data model is the same as in Armoria and covered in API documentation. The only additional fields are optionalsize
:number
,x
:number
andy
:number
that controls the emblem position on the map (if it's not default). If emblem is loaded by user, then the value is{ custom: true }
and cannot be displayed in Armorialock
:boolean
-true
if state is locked (not affected by regeneration)removed
:boolean
-true
if state is removed
Regiment
i
:number
- regiment id, equals to the array index of regiment in thestate[x].military
array. Not unique, as unique stringregimentStateId-regimentId
is usedx
:number
- regiment x coordinatey
:number
- regiment y coordinatebx
:number
- regiment base x coordinateby
:number
- regiment base y coordinateangle
:number
- regiment rotation angle degreeicon
:number
- Unicode character to serve as an iconcell
:number
- original regiment cell idstate
:number
- regiment state idname
:string
- regiment namen
:number
-1
if regiment is a separate unit (like naval units),0
is notu
:Record<unitName, number>
- regiment content object
Provinces
Provinces data is stored as an array of objects with strict element order. Element 0 is not used. If religion is removed, the element is not getting removed, but instead a removed
attribute is added. Object structure:
i
:number
- province id, always equal to the array indexname
:string
- short (proper) form of the province nameformName
:string
- string form name, used to get provincefullName
fullName
:string
- full state name. Combination of the proper name and provinceformName
color
:string
- province color in hex (e.g.#45ff12
) or link to hatching pattern (e.g.url(#hatch7)
)center
:number
- cell id of province center (initial cell)pole
:number[]
- province pole of inaccessibility (visual center) coordinates, see the concept descriptionarea
:number
- province area in pixelsburg
:number
- id of province capital burg if anyburgs
:number[]
- id of burgs within the province. Optional (added when Province editor is opened)cells
:number
- number of cells within the provincerural
:number
- rural (non-burg) population of province cells. In population pointsurban
:number
- urban (burg) population of state province. In population pointscoa
:object
- emblem object, data model is the same as in Armoria and covered in API documentation. The only additional fields are optionalsize
:number
,x
:number
andy
:number
that controls the emblem position on the map (if it's not default). If emblem is loaded by user, then the value is{ custom: true }
and cannot be displayed in Armorialock
:boolean
-true
if province is locked (not affected by regeneration)removed
:boolean
-true
if province is removed
Religions
Religions data is stored as an array of objects with strict element order. Element 0 is reserved for "No religion". If province is removed, the element is not getting removed, but instead a removed
attribute is added. Object structure:
i
:number
- religion id, always equal to the array indexname
:string
- religion nametype
:string
- religion type. Available types areFolk
,Organized
,Heresy
andCult
form
:string
- religion formdeity
:string
- religion supreme deity if anycolor
:string
- religion color in hex (e.g.#45ff12
) or link to hatching pattern (e.g.url(#hatch7)
)code
:string
- religion name abbreviation. Used to render religions treeorigins
:number[]
- ids of ancestor religions.[0]
if religion doesn't have an ancestor. Used to render religions tree. The first array member is main link, other - supporting out-of-tree linkscenter
:number
- cell id of religion center (initial cell)culture
:number
- religion original cultureexpansionism
:number
- religion growth multiplier. Used during religion generation to define competitive sizeexpansion
:string
- religion expansion type. Can beculture
so that religion grow only within its culture orglobal
area
:number
- religion area in pixelscells
:number
- number of cells within the religionrural
:number
- rural (non-burg) population of religion cells. In population pointsurban
:number
- urban (burg) population of state religion. In population pointslock
:boolean
-true
if religion is locked (not affected by regeneration)removed
:boolean
-true
if religion is removed
Rivers
Rivers data is stored as an unordered array of objects (so element id is not the array index). Object structure:
i
:number
- river idname
:string
- river nametype
:string
- river type, used to get river full name onlysource
:number
- id of cell at river sourcemouth
:number
- id of cell at river mouthparent
:number
- parent river id. If river doesn't have a parent, the value is self id or0
basin
:number
- river basin id. Basin id is a river system main stem id. If river doesn't have a parent, the value is self idcells
:number[]
- if of river points cells. Cells may not be unique. Cell value-1
means the river flows off-canvaspoints
:number[][]
- river points coordinates. Auto-generated rivers don't have points stored and rely oncells
for renderingdischarge
:number
- river flux in m3/slength
:number
- river length in kmwidth
:number
- river mouth width in kmsourceWidth
:number
- additional width added to river source on rendering. Used to make lake outlets start with some width depending on flux. Can be also used to manually create channels
Markers
Markers data is stored as an unordered array of objects (so element id is not the array index). Object structure:
i
:number
- marker id.'marker' + i
is used as svg element id and marker reference innotes
objecticon
:number
- Unicode character (usually an emoji) to serve as an iconx
:number
- marker x coordinatey
:number
- marker y coordinatecell
:number
- cell id, used to prevent multiple markers generation in the same celltype
:string
- marker type. If set, style changes will be applied to all markers of the same type. Optionalsize
:number
- marker size in pixels. Optional, default value is30
(30px)fill
:string
- marker pin fill color. Optional, default is#fff
(white)stroke
:string
- marker pin stroke color. Optional, default is#000
(black)pin
:string
: pin element type. Optional, default isbubble
. Pin is not rendered if value is set tono
pinned
:boolean
: if any marker is pinned, then only markers withpinned = true
will be rendered. Optionaldx
:number
- icon x shift percent. Optional, default is50
(50%, center)dy
:number
- icon y shift percent. Optional, default s50
(50%, center)px
:number
- icon font-size in pixels. Optional, default is12
(12px)lock
:boolean
-true
if marker is locked (not affected by regeneration). Optional
Routes
Routes data is stored as an unordered array of objects (so element id is not the array index). Object structure:
i
:number
- route id. Please note the element with id0
is a fully valid route, not a placeholderpoints
:number[]
- array of control points in format[x, y, cellId]
feature
:number
- feature id of the route. Auto-generated routes cannot be place on multiple featuresgroup
:string
- route group. Default groups are: 'roads', 'trails', 'searoutes'length
:number
- route length in km. Optionalname
:string
- route name. Optionallock
:boolean
-true
if route is locked (not affected by regeneration). Optional
Zones
Zones data is stored as an array of objects with i
not necessary equal to the element index, but order of element defines the rendering order and is important. Object structure:
i
:number
- zone id. Please note the element with id0
is a fully valid zone, not a placeholdername
:string
- zone descriptiontype
:string
- zone typecolor
:string
- link to hatching pattern (e.g.url(#hatch7)
) or color in hex (e.g.#45ff12
)cells
:number[]
- array of zone cellslock
:boolean
-true
if zone is locked (not affected by regeneration). Optionalhidden
:boolean
-true
if zone is hidden (not displayed). Optional
Secondary global data
Secondary data exposed to global space.
Biomes
Biomes data object is globally available as biomesData
. It stores a few arrays, making it different from other data. Object structure:
i
:number[]
- biome idname
:string[]
- biome namescolor
:string[]
- biome colors in hex (e.g.#45ff12
) or link to hatching pattern (e.g.url(#hatch7)
)biomesMartix
:number[][]
- 2d matrix used to define cell biome by temperature and moisture. Columns contain temperature data going from >19
°C to <-4
°C. Rows contain data for 5 moisture bands from the drier to the wettest one. Each row is aUint8Array
cost
:number[]
- biome movement cost, must be0
or positive. Extensively used during cultures, states and religions growth phase.0
means spread to this biome costs nothing. Max value is not defined, but5000
is the actual max used by defaulthabitability
:number[]
- biome habitability, must be0
or positive.0
means the biome is uninhabitable, max value is not defined, but100
is the actual max used by defaulticons
:string[][]
- non-weighed array of icons for each biome. Used for relief icons rendering. Not-weighed means that random icons from array is selected, so the same icons can be mentioned multiple timesiconsDensity
:number[]
- defines how packed icons can be for the biome. An integer from0
to150
Notes
Notes (legends) data is stored in unordered array of objects: notes
. Object structure is as simple as:
i
:string
- note idname
:string
- note name, visible in Legend boxlegend
:string
- note text in html
Name bases
Name generator consumes training sets of real-world town names (with the exception of fantasy name bases) stored in nameBases
array, that is available globally. Each array element represent a separate base. Base structure is:
i
:number
- base id, always equal to the array indexname
:string
- names base proper nameb
:string
- long string containing comma-separated list of namesmin
:number
- recommended minimal length of generated names. Generator will adding new syllables until min length is reachedmax
:number
- recommended maximal length of generated names. If max length is reached, generator will stop adding new syllablesd
:string
- letters that are allowed to be duplicated in generated namesm
:number
- if multi-word name is generated, how many of this cases should be transformed into a single word.0
means multi-word names are not allowed,1
- all generated multi-word names will stay as they are