MapGeneratorWML

From The Battle for Wesnoth Wiki
Revision as of 18:04, 26 July 2022 by Soliton (talk | contribs) (YAMG was removed a long time ago.)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Map Generator WML is used to create scenarios which are randomly generated. Of course, any scenario may reconfigure itself during a start / prestart event as much as it likes, using randomness, but the Map Generator WML has the following advantages:

  • Wesnoth has several built-in map generators which can be configured with options, and these are much better developed than any existing pure WML options.
  • Map generation occurs before the scenario is even loaded, something which is not possible for WML events. In an mp game, the map generator code will run only on the host, side-stepping any synchronization issues, and keeping your scenario code as simple as possible.
  • For scenarios with "allow_new_game=yes" and which use map generators, the generator may be reconfigured in the mp create screen (assuming that someone has coded a dialog for it). The user can also select to regenerate the map and get instant feedback from the minimap display.

Scenario vs map generation

Every map generator can be used in either scenario_generation mode or map_generation mode. In map_generation mode, the generator is only used to replace the map_data of your scenario. In scenario_generation mode, the entire [scenario] tag is replaced.

To select a map generator and mode, in your [scenario] tag you must place one of

  • scenario_generation=algorithm
  • map_generation=algorithm

where algorithm is the generator algorithm you want to use. Note that not every algorithm is designed to be use with both of these options.

You must additionally place a [generator] tag in your scenario, which contains the options to the map generator.

The [scenario] tag must leave both map_data and map_file unset, or set them to empty strings, otherwise the behavior is implementation defined; the engine might assume that the generator has already been run, and skip running it.

[generator]

The exact things that should be placed in [generator] depend on what algorithm you pick. There are three kinds of generators, default, cave (cave is removed in wesnoth 1.13.6), lua (Version 1.13.0 and later only)

For which key to use and what value, see the section for the generator you want to use.

The lua generator

The lua generator type specifies a custom map generator, which you provide via lua scripts.

The following keys are recognized for [generator] when the lua generator is used:

  • create_map : A lua routine which returns a string containing the new map_data. The entire contents of the [generator] are passed to the script in a lua table (see LuaWML), via the argument ... (see http://www.lua.org/pil/5.2.html).
  • create_scenario : The same, but returning a [scenario] tag for the new scenario, as a lua table.

Any other keys are used only by the lua script.

The following keys of the output [scenario] are specifically watched by the mp create screen:

  • id
  • name
  • description
  • error_message

Available Lua API

Most of the usual in-game API, in the table wesnoth, is not available to lua scripts. However the usual standard lua libs are available, and a random number generator object is available from the Rng table. This is an instance of the Mersenne Twister 19937 random number generator from the C++11 standard.

  • rng = Rng:create() : creates a new rng object
  • rng:seed() : seed an rng, expects a string in hexadecimal format
  • rng:draw() : draw a 32-bit random integer from the rng

It is highly recomended NOT to use the math.random function in random map generators, becasue math.random breaks the 'seed' function for random map generators in the editor.

(Version 1.13.x (please read the template documentation to set the correct version number) and later only) In 1.13.x, this is no longer the case; much of the wesnoth table is available, including (but not limited to) wesnoth.random and wesnoth.find_path. However, there are still many things that are not available. You can open a Lua console to experiment and find out what's allowed by calling wesnoth.show_lua_console at some point in your map generator script. The Rng table no longer exists, having been superceded by wesnoth.random.

The Default Generator

The default generator can be used to generate map data for any scenario. The data in this section is inferred from “data/multiplayer/scenarios/Random_Scenario.cfg”, usage in add-on content, and inspection of mapgen.cpp

Excerpt from mapgenerator comments:

  • Basically we generate alot of hills, each hill being centered at a certain point, with a certain radius - being a half sphere. Hills are combined additively to form a bumpy surface. The size of each hill varies randomly from 1-hill_size. We generate 'iterations' hills in total. The range of heights is normalized to 0-1000. 'island_size' controls whether or not the map should tend toward an island shape, and if so, how large the island should be. Hills with centers that are more than 'island_size' away from the center of the map will be inverted (i.e. be valleys). 'island_size' as 0 indicates no island.

To use the default [generator] your [scenario] tag must contain one of the following keys:

  • scenario_generation=default
  • map_generation=default

If ‘scenario_generation’ is used, the engine will expect for your entire [scenario] sub tags to be inside a [scenario] tag inside [generator]. Tags outside of this will be ignored. There may be value in this, but at this writing, it’s not clear. ‘map_generation=default’ is simpler and more commonly used. It is also necessary to use this key so that you can regenerate a map in MP game creation. In its use only generator data is in the [generator] tag, all other [scenario] data is placed outside of it. The exception is if you are making an initial MP scenario available in MP game creation, for this a [scenario] tag must appear inside of [generator], containing the [scenario] subtags you want to use. See “data/multiplayer/scenarios/Random_Scenario.cfg” for an example.

The following key/tags are recognized for [generator] when the default generator is used:

  • [scenario]: See ScenarioWML
  • name
    • default
  • map_width,map_height: size of the map to generate
  • iterations: the number of times an attempt is being made to generate a hill
  • hill_size: hills will have a random size between 1 and hill_size
  • max_lakes: the number of times an attempt is being made to generate a lake
  • min_lake_height: lakes are the starting point of rivers and need to start above a certain height
  • lake_size: the size of a lake still randomly generated
  • river_frequency: determine how much a river can run uphill and thus generate more rivers
  • villages: villages per 1,000 hexes
  • players: Number of starting locations for the map.
  • castle_size: Number of castle tiles (including the keep), per player.
  • temperature_iterations: Same as iterations, but for the temperature map.
  • temperature_size: Same as hill_size, but for the temperature map. (Temperature map is generated the same way as a hill map, but is hard coded with a island_size of 0.)
  • roads: number of roads the generator will attempt to make
  • road_windiness: Use 1 for the road to be made using the cheapest path (based on [road_cost] tags), higher values introduce randomness to make the road wind a bit.
  • island_size: Use 1-5 for coastal maps and 6-10 for island maps. Bigger values may crash map generation process. Bigger numbers makes more water (and less land)
  • default_flatland: If not specified, is Grassland. If your height tags don't go down to 0, the default_flatland will be used (possibly in other cases as well).
  • [height]: list of common terrain types that come in at different heights, from highest to lowest. Good WML will have the range of 1000-0 covered.
    • height: the terrain specified below will appear at this height and up.
    • terrain: 1 terrain code
  • [convert]: used to make terrain conversions. For example, water becomes ice at low temperatures, grass snow, etc. If the terrain is between the min_x and max_x it will be converted. If min_x is not defined it will default to a large negative number. If max_x is not defined it will default to a large positive number
    • min_height
    • max_height
    • min_temperature
    • max_temperature
    • from: a comma separated terrains to convert from
    • to: The terrain to convert these terrains to
  • [road_cost]
    • terrain 1 terrain code
    • cost: how expensive it is the create a road on this terrain, this influences the odds of this terrain getting a road
    • convert_to_bridge: a comma separated list of terrains; N/S, then NE/SW, then NW/SE.
    • convert_to: 1 terrain code (note using both convert_to_bridge and convert_to might result in unwanted results)
  • [village]: The conversion of terrains to villages
    • terrain: 1 terrain code which will be converted to a village
    • convert_to: 1 terrain code for the village
    • adjacent_liked: a comma separated terrain list. This list increases the rating for a certain location, every tile around the location will be tested against this list and for every match the rating of the location is increased. The same terrain twice in the list will double the rating increase for that location.
    • rating: chance of appearing
  • [castle]: the conversion of castles
    • valid_terrain: a comma-separated terrain list with terrains which are allowed to be converted to a castle.
    • min_distance: all castles generated must be this number of hexes apart from each other
  • [naming]: The names used to label landscape features (forests, lakes, etc.). This controls, for example, the "Sal" part of "Sal's Crossing". If this tag is empty, those labels should be suppressed. (Due to a bug, they are not suppressed prior to 1.11.1.) The predefined macro VILLAGE_NAMES is one option for the contents of this tag. If that macro is not used, this tag takes one key.
    • (Version 1.13.5 and later only)
      • The new Context-free grammar name (CFG) generator is now supported
      • male_names is now deprecated. Use base_names for the Markov-chain based or base_name_generator for the CFG generator instead
      • It is now possible to have generator-specific overrides of the default naming rules which are defined in "data/english.cfg". You may override the following naming rules by adding them to the [naming] tag of your generator instance:
Key Supported variables
bridge_name_generator= $base
road_name_generator= $base
river_name_generator= $base
forest_name_generator= $base
lake_name_generator= $base
mountain_name_generator= $base
swamp_name_generator= $base
  • [village_naming]: The names used to label villages. This controls, for example, the "Fox" part of "Foxham". If this tag is empty, those labels should be suppressed. (Due to a bug, they are not suppressed prior to 1.11.1.) The predefined macro VILLAGE_NAMES is one option for the contents of this tag. If that macro is not used, this tag takes one key. The village naming depends on the adjacent landscape features, e.g. a village near a forest with the name "Rock Forest" may be named "Rockwood".
    • male_names
    • (Version 1.13.5 and later only)
      • The new Context-free grammar name (CFG) generator is now supported
      • male_names is now deprecated. Use base_names for the Markov-chain based or base_name_generator for the CFG generator instead
      • It is now possible to have generator-specific overrides of the default village naming rules which are defined in "data/english.cfg". You may override the following village naming rules by adding them to the [village_naming] tag of your generator instance:
Key Supported variables
name_generator= $base
lake_name_generator= $base, $lake
river_name_generator= $base, $river
bridge_name_generator= $base, $river, $bridge
grassland_name_generator= $base
forest_name_generator= $base, $forest
hill_name_generator= $base
mountain_name_generator= $base, $mountain
mountain_anon_name_generator= $base
road_name_generator= $base, $road
swamp_name_generator= $base, $swamp

The Cave Generator

The cave generator generates a system of chambers and passages similar to the levels in dungeon crawling games like Rogue. It does not appear to have been written for multiplayer scenario game creation like the default generator was. It is used in campaigns\Sceptre_of_Fire\scenarios\4_Gathering_Materials.cfg & campaigns\Heir_To_The_Throne\scenarios\ 17_Scepter_of_Fire.cfg . The data here is inferred from those scenarios and an inspection of cavegen.cpp

To use the cave [generator] your [scenario] tag must contain one of the following keys:

  • scenario_generation=cave
  • map_generation=cave

Here it is recommend you use ‘scenario_generation’ as there are examples to follow, though it may be possible to use’ map_generation’.


The following key/tags are recognized for [generator] when the cave generator is used:

  • [settings]: behaves as if [scenario], See ScenarioWML
  • map_width,map_height: size of the map to generate
  • village_density: influences number of villages
  • flipx_chance: Chance to flip x coordinates, that meens the map is mirrored at the vertical axis in its midth.
  • flipy_chance: Chance to flip y coordinates, that meens the map is mirrored at the horizontal axis in its midth.
  • [chamber]: for underground maps
    • id: a name used to identify where the passages lead. See the [passage] tag, below.
    • x,y: approximate location of the center hex of the chamber. Unfortunately it isn't always exact. Can be a single number (x=5) or a range (x=10-20)
    • size: circular radius of the chamber, including the center hex
    • jagged: a good value is probably between 0-50 (not sure exactly)
    • chance: chance for the chamber to be generated, between 0 and 100, 100 if key not present
    • [items]: See ScenarioWML. This can contain tags normally found under [scenario] like [side], [item], and [event]. Moveto events definitely work here (using the same_location_as_previous key instead of a location filter). Other events can be placed in the [settings] tag, above. Locations of items will be generated randomly. The attribute same_location_as_previous=yes means that the filter for a moveto event (see EventWML) is the same as the location of the previous item.
    • [passage]: defines a pathway between chambers
      • destination: the id key of the destination chamber
      • windiness: a good value is probably between 1-10
      • laziness:
      • width: number of hexes
      • jagged: a good value is probably between 1-10
      • chance: chance for the passage to be generated, between 0 and 100, 100 if key not present

(Version 1.13.6 and later only) The cave map generator has been moved to Lua, so scenario_generation=cave and map_generation=cave are no longer supported. Use one of the following setups instead:

  • Map generation:
map_generation=lua
[generator]
    create_map = << return wesnoth.require("cave_map_generator").generate_map(...) >>
    # ... other stuff ...
[/generator]
  • Scenario generation:
scenario_generation=lua
[generator]
    create_scenario = << return wesnoth.require("cave_map_generator").generate_scenario(...) >>
    # ... other stuff ...
[/generator]

The [generator] supports the same syntax if using scenario_generation, but has the following differences when using map_generation:

  • [items] is not supported. Use one or multiple [item_location] instead. This will generate starting locations or other special locations in the map data with the given id; place_castle = yes can be set in [item_location] to make the generator create a castle at this location.
  • [settings] is not supported - '[event]s' and '[side]s' now go directly in [scenario]

Infrastructure

  • The default generator settings are loaded from a scenario file under data/multiplayer/scenarios.
  • mapgen_dialog overwrites these values if necessary.
  • The create_map / create_scenario function is called by one of the following
    • multiplayer_create_engine.cpp:394
    • context_manager.cpp:648
    • map_create.cpp:56
  • A map buffer is written to res["map_data"]
  • the config res is passed to the calling function.

See Also

This page was last edited on 26 July 2022, at 18:04.