LuaAPI/wesnoth/map

From The Battle for Wesnoth Wiki
< LuaAPI‎ | wesnoth
Revision as of 02:23, 24 February 2021 by Celtic Minstrel (talk | contribs) (Add on_board and on_border)

(Version 1.15.11 and later only)

This documents the un-merged pull request 4580

wesnoth.map.find

  • (game only) wesnoth.map.find(filter config) → list of hex references
  • (game only) wesnoth.map.find(filter config [, reference_unit]) → list of hex references
  • (mapgen only) wesnoth.map.find(map, filter userdata [, list of locations]) → list of locations
  • (mapgen only) wesnoth.map.find_in_radius(map, center, radius, filter userdata) → list of locations

Returns a table containing all the locations matching the given filter. Locations are stored as a hex reference which has x and y keys along with a variety of other functions. See StandardLocationFilter for details about location filters. If a unit is passed, it can be referenced from the filter via the $teleport_unit variable, as well as in WFL formulas used in the filter.

Note: In older versions of Wesnoth, locations returned from a filter were stored as simple pairs, {x,y}. For compatibility purposes, accessing a location this way (as loc[1] and loc[2]) is still supported.

-- replace all grass terrains by roads
for i,loc in ipairs(wesnoth.map.find{terrain = "Gg"}) do
    wesnoth.current.map[loc] = "Rr"
end

The mapgen form of this function uses a different format for the filter which is somewhat experimental. An example of its use:

local map = wesnoth.map.create(18,18,"Gg")

-- Assume there is some generation code here, so the map is no longer just grass

local F, f = wesnoth.map.filter, wesnoth.map.filter_tags

-- Find all elvish villages
local elf_villages = map:find(F(f.terrain('*^Ve')))

-- Find all great trees within 7 tiles of an elvish keep
local elf_keeps = map:find(F(f.terrain('Kv')))
local nearby_trees = map:find_in_radius(elf_keeps, 7, F(f.terrain('*^Fet')))

Possible filter tags for this function are: terrain, all, any, none, notall, adjacent, find_in, radius, x, y, is_loc, formula.

wesnoth.map.get

  • (game only) wesnoth.map.get(location) → hex reference

Constructs a hex reference for the specified location.

wesnoth.map.matches

  • wesnoth.map.matches(location, filter [, reference_unit]) → boolean
  • hex:matches(filter, [, reference_unit]) → boolean

Returns true if the given location passes the filter. The location can be passed either as two separate x and y parameters or as an object with x and y keys (such as a hex reference or a unit). If a reference_unit is passed, it can be referenced from the filter via the $teleport_unit variable, as well as in WFL formulas used in the filter.

local b = wesnoth.map.matches(x, y, {
    terrain = "Ww",
    wml.tag.filter_adjacent_location{terrain = "Ds,*^Bw*"}
})

wesnoth.map.on_board

  • wesnoth.map.on_board(map, location [, include border?]) → boolean
  • map:on_board(location, [, include border?]) → boolean

Tests if the specified location is on the map. The final parameter determines whether to count the inaccessible map border tiles as being on the map. It defaults to false.

wesnoth.map.on_border

  • wesnoth.map.on_border(map, location) → boolean
  • map:on_border(location) → boolean

Tests if the specified location is on the map's border.

wesnoth.map.read_location

  • wesnoth.read_location(...) → location or nil, number of arguments processed

Extracts a location from the front of a variadic parameter list. The purpose of this is to make it easy for custom user-defined functions to handle locations in the same way as the built-in API functions do. It returns the location (if it was able to find one) and the number of arguments processed, which can be:

  • 0 if nothing resembling a location was found.
  • 1 if a location-like object was found. A location-like object can be either an array of two integers or an object that has numeric x and y keys. Note that a unit userdata satisfies the second criteria, so if a unit is found, its location will be returned.
  • 2 if the first two arguments in the list were integers. In this case, they will be taken as the x and y coordinates.

Usage example

Imagine a function foo with the following signature:

  • foo(bar : string, [home : location], mode : string, [target : location], moo : boolean) → boolean

Using read_location it could be implemented as follows:

function foo(...)
	-- First argument goes in bar
	local bar = ...
	-- Read location starting at the second argument
	local home, n = wesnoth.map.read_location(select(2, ...))
	-- note: n will be 0 if a location wasn't found at that position
	-- This could be an error, or it could be handled as an optional parameter
	-- Next argument after that goes in mode
	local mode = select(n + 2, ...)
	-- Then read a location into target
	local target, m = wesnoth.map.read_location(select(n + 2, ...))
	-- Finally, read a parameter into moo
	local moo = select(m + n + 2, ...)
	-- Do stuff with all these parameters
	return true
end

With that code, all the following invocations of foo work:

foo('a', 'b', true) -- both optional locations omitted
foo('a', 1, 2, 'q', 5, 6, false) -- locations given as separate integer parameters
foo('a', 'm', {1, 7},  true) -- first location omitted, second given as 2-element array
foo('a', some_unit, 'z', {x = 5, y = 10}, false) -- a unit also functions as a location
foo('a', 7, 12, 'q', my_leader, true) -- mixing different forms also works

wesnoth.map.split_terrain_code

  • wesnoth.map.split_terrain_code(code) → base, overlay

Splits a terrain code into a base and an overlay. If the terrain code did not contain a ^, then the overlay will be nil. The returned overlay or base can be an empty string if the code begins or ends with a ^, respectively. Splitting the string '^' will result in two empty strings.

wesnoth.map.terrain_mask

  • wesnoth.map.terrain_mask(map, pivot, mask [, options])
  • map:terrain_mask(pivot, mask [, options])

Overlays a terrain mask on the map. Possible options:

  • is_odd - if true, then the mask is interpreted as if it was cut out from an odd map location.
  • ignore_special_locations - if true, then special locations on the mask won't be added to the map.
  • rules - an array of rules. See TerrainMaskWML for the rule format. This is an array of tables, each of which has the content of a [rule] tag.

wesnoth.map.get_direction

  • wesnoth.map.get_direction(from, dir [, steps]) → location

Calculates the hex reached by travelling in the specified direction, which should be a string such as "ne" or "s". It will also honor direction modifiers (the prefix - and postfix :cw or :ccw). The optional third parameter steps is number of steps to travel in specified direction. Negative steps is supported to travel in the opposite direction.

wesnoth.map.get_relative_dir

  • wesnoth.map.get_relative_dir(from, to) → direction

Calculates the direction from one hex to another. Possible returns are strings "n", "ne", "nw", "s", "se", "sw" or "". The empty string means no direction which happens if from and to are same.

wesnoth.map.rotate_right_around_center

  • wesnoth.map.rotate_right_around_center(loc, center, angle) → location

Calculates the hex obtained from rotating the specified location around the specified center by the specified angle. The angle is an integer in the range 1..6.

wesnoth.map.get_adjacent_hexes

  • wesnoth.map.get_adjacent_hexes(loc) → n, ne, se, s, sw, nw

Return all hexes adjacent to the specified hex, as six separate return values. This doesn't check whether the hexes are on the map.

local a, b, c, d, e, f = wesnoth.map.get_adjacent_hexes(3, 3)
local a_x = a[1]
local a_y = a[2]

wesnoth.map.get_hexes_in_radius

  • wesnoth.map.get_hexes_in_radius(center, radius) → list of locations

Return all hexes within the given radius, as an array of pairs. This doesn't check whether the hexes are on the map.

wesnoth.map.are_hexes_adjacent

  • wesnoth.map.are_hexes_adjacent(loc1, loc2) → boolean

Tests if two hexes are adjacent.

wesnoth.map.distance_between

  • wesnoth.map.distance_between(loc1, loc2) → boolean

Calculates the distance between two hexes.

local my_distance = wesnoth.map.distance_between({10, 10}, {20, 20})