18 Random_Map_Generator_Internals
phosit edited this page 2024-05-28 21:35:39 +02:00

This document describes the interaction between the engine and the random map scripts.

Defining the Map

Random maps have various metadata associated with them, which is stored in a JSON data file. The possible settings are mostly shared with scenarios, but there are some differences. The benefit of using a separate file for metadata is that it allows a single random map script to behave differently given different metadata as input, and the object format is convenient for parsing in scripts. Here is a simple example:

{
	"settings" : {
		"Name" : "Islands",
		"Script" : "islands.js",
		"Description" : "Players start in small islands while there are many others around...",
		"BaseTerrain" : ["medit_sand_wet"],
		"BaseHeight" : -5,
		"Keywords": ["naval"],
		"Preview" : "islands.png",
		"CircularMap" : true
	}
}

Note: there is a parent object called settings, which contains all the other properties as its children, described below.

Settings List

Here is the current list of settings available to random map scripts:

Required constants:

  • Name: (string) The name of the map, only used for display purposes.
  • Script: (string) Filename of the associated map script.
  • Description: (string) Brief description of the map, shown in game setup.
  • BaseTerrain: (array of strings) At least one terrain texture that will form the primary terrain of the map. These are actual texture filenames without the extension.
  • BaseHeight: (integer) Base height of the terrain, basically how deep water can be vs. how high mountains can be.

Optional / game setup values:

  • Preview: (string) Optional. Filename of preview image for this map, shown in game setup.
  • CircularMap: (bool) Optional. Indicates whether the map is circular (default) or square. This effects how map bounds work, for instance.
  • RevealMap: (bool) Optional. Indicates whether the map should be revealed for all players (no LOS), default is false. Can be useful for testing.
  • Keywords: (array of strings) Optional. List of keywords for this map, which can be used to filter it out in the game setup menu. Examples: "demo", "naval", or "hidden".
  • LockTeams: (bool) Optional. Indicates whether teams (and thus diplomacy) should be locked when the game begins, default is false.
  • VictoryConditions: (array) List of victory conditions to be used in the game. No victory conditions is interpret as an endless game.
  • Size: (integer) Size of the map in tiles (see [map_sizes.json]source:ps/trunk/binaries/data/mods/public/simulation/data/map_sizes.json).
  • PlayerData: (array of objects) Array of player data objects, [player_defaults.json]source:ps/trunk/binaries/data/mods/public/simulation/data/player_defaults.json is used to fill in missing data.
  • AI: (string) Name of the AI for this player.
  • Civ: (string) Four-letter code for the player's civ e.g. "hele".
  • Name: (string) Name of this player.
  • Colour: (object) Player colour with integer RGB properties: {"b": 13, "g": 13, "r": 166}
  • Team: (integer) Team number for this player or -1 for no team (default).
  • Diplomacy: (array of integers) Diplomatic association of this player with all others, typically unused in favor of Team, but can be used to construct complex unilateral diplomacies. Other custom properties can be defined too, or placeholders used for documenting.

Generating the Map

When loading a scenario, the CMapReader class simply reads an XML file (with map settings, list of entities, and other textual data) together with a binary file called a PMP (which specifies height map and terrain textures). For a random map, there is obviously no predefined map data to load. Instead, the engine uses a new CMapGenerator class. The CMapGenerator needs the name of a random map script and some settings, such as number of players and their civs. These are selected during game setup.

Engine-script interface

After the script file is run the engine calls GenerateMap. GenerateMap is searched in the global object. The argument to GenerateMap is an object containing the map settings. The map settings are created by the game setup. When GenerateMap yields a it's progress (an integer from 1 to 100) the progress bar is updated accordingly. The (final) returned map eitherhas to be of the format described below or have a function MakeExportable which returns an object of that format. This is done so that libraris can do some cleanup in MakeExportable.

The engine exposes some JavaScript functions:

  • Engine.LoadLibrary(name) - load a library, choosing the API to which a random map script will have access, e.g. "rmgen".
  • Engine.GetCivData() - returns an array of civilization data from /civs/*.json, which is useful for determining civ-specific units and structures.
  • Engine.GetTemplate(templateName) - returns an array containing the data of the requested template.
  • Engine.MaybeGC() - possibly run the garbage collector.

The use of this functions is deprecated. The generator based interface described above should be used.

  • Engine.ExportMap(data) - export generated map data from the scripts to the engine.
  • Engine.SetProgress(percent) - set the map generation progress percentage, so the loading screen progress bar can be updated. Percentage must be an integer 1-100. There is also a global g_MapSettings which is also deprecated.

Data format

The data from a random map script must be in an exact format, independent of the methods used to generate it. This format can be specified in JSON as follows:

{
  "size": 128,
  "height": [ 1000, ... ]
  "seaLevel": 20.0,
  "textureNames": [ "medit_grass_field_a", ... ]
  "tileData": { "index": [0, 1, 0, 0, 2, ... ], "priority": [0, 1, 0, 0, 2, ... ] }
  "entities": [ { "id": 100, "templateName": "units/hele_support_female_citizen", "position": {"x": 102.4, "y": 0, "z": 64.8}, "rotation": {"x": 0, "y": 0.86, "z": 0} }, ... ]
}
  • size: Integer. This is the size of the map in tiles.
  • height: Flat array of 16-bit unsigned integers. This is the height data for each tile of the map.
  • seaLevel: Float. This is the height of the sea, the value in the heightmap for which all lower terrain will be under water.
  • textureNames: Array of strings. This is the terrain textures used. They must be in the order in which they were defined (as they are referenced by tile data).
  • tileData: Object. Contains two flat arrays specifying terrain tile data for the map - see below.
  • entities: Array of entity objects. Entities specify something like a tree, soldier, or building in the game - see below.

Tile Data

{
  "index" : [0, 1, 0, 0, 2, ... ],
  "priority" : [0, 1, 0, 0, 2, ... ]
}

Originally this was an array of tile descriptor objects but the size of the resulting map data was greatly reduced by using two typed arrays. This data does not need to consider patches, this will all be handed by CMapReader.

  • indexes: Flat array of 16-bit unsigned integers. Texture ID to be used for each tile (value is referenced from textureNames array).
  • priority: Flat array of 16-bit unsigned integers. Optional priority for texture blending each tile (value of 0 is default). Considering adjacent tiles, the texture with higher priority will be blended on top of the tiles with lower priorities.

Entity format

  "id": 1034,
  "templateName": "units/hele_support_female_citizen",
  "position": {"x": 102.4, "y": 0, "z": 64.8},
  "rotation": {"x": 0, "y": 0.86, "z": 0}
  • id: Integer. Unique ID of this entity, used by the engine to identify each instance.
  • templateName: String. Template name of the entity, usually specifies faction and unit/building type for players, or special gaia templates.
  • position: 3D vector object. Position of the entity, in tile grid coordinates. Note: the y position (height) is not currently supported.
  • rotation: 3D vector object. Rotation of the entity, in radians. Note: only rotation about y-axis (vertical) is currently supported.

CMapReader is responsible for parsing this data and creating the map, in a process very similar to that for scenarios.