LuaWML/Location set

From The Battle for Wesnoth Wiki



This page describes the LuaWML class for handling location sets and location maps. Objects of this class store a set of locations, with some data (boolean true, by default) attached to each of them. It is not possible to associate nil or false to a location.

There is one main constructor #location_set.create and two auxiliary helper constructors #location_set.of_pairs and #location_set.of_wml_var. They are provided by the lua/location_set.lua file. All the other functions are methods from the class and they are available through the ':' operator only.

local location_set = wesnoth.require "lua/location_set.lua"
local a_set = location_set.create()
a_set:insert(17, 42, "something")
assert(a_set:get(17, 42) == "something")
local b_set = location_set.of_pairs(wesnoth.get_locations { { "filter_adjacent", { x=17, y=42 } } })
a_set:union(b_set)
a_set:to_wml_var "locations"

location_set.create

Returns an empty location set.

location_set.of_pairs

Returns a fresh location set filled by #location_set:of_pairs.

location_set.of_wml_var

Returns a fresh location set filled by #location_set:of_wml_var.

location_set:empty

Returns true if the set is empty.

local some_set = location_set.create()
assert(some_set:empty())

location_set:size

Returns the number of locations in the set.

some_set:insert(17, 42)
assert(some_set:size() == 1)

location_set:clear

Empties the content of the set.

some_set:clear()
assert(not some_set:get(17, 42))

location_set:get

Returns the data associated to the given location or nil if the location is not in the set.

some_set:insert(17, 42, "something")
assert(some_set:get(17, 42) == "something")

location_set:insert

Associates some data to the given location, or true if there is no data. Previous associated data is lost.

some_set:insert(17, 42)
assert(some_set:get(17, 42))

location_set:remove

Removes the given location from the set.

some_set:remove(17, 42)

location_set:of_pairs

Inserts all the locations from an array containing pairs (arrays with two elements). Previous content of the set is kept, unless overwritten by the content of the array.

some_set:of_pairs(wesnoth.get_locations { { "filter_adjacent", { x=17, y=42 } } })

Can also read in tables with location tables of the form {x = some_number, y = some_number} like what is returned by ai.get_avoid().

some_set:of_pairs(ai.get_avoid())

If any extra data is included in the table for an individual location in the input, it will be put into a table and associated with that location's index in the location_set. Otherwise the data associated with a location's index is "true".

location_set:of_wml_var

Inserts all the locations from a WML array. If a container has more than just x and y attributes, the remaining attributes and children are associated to the location as a WML table. Previous content of the set is kept, unless overwritten by the content of the WML array.

wesnoth.wml_actions.store_locations { variable="target", { "filter_adjacent", { x=17, y=42 } } }
some_set:of_wml_var "target"

location_set:to_pairs

Returns an array of pairs containing the locations of the set. Associated data are ignored. The order of the locations is not deterministic. If the order actually matters, the #location_set:to_stable_pairs method should be used instead.

local size = #(some_set:to_pairs())

location_set:to_stable_pairs

Returns an array of pairs containing the locations of the set. Contrarily to #location_set:to_pairs, the locations are guaranteed to be sorted and hence synchronized over networks and replays.

location_set:to_wml_var

Fills a WML array with the content of the set. The order of the elements is safe.

local some_set = location_set.of_pairs(wesnoth.get_locations { { "filter_adjacent", { x=17, y=42 } } })
some_set:to_wml_var "locations"

location_set:union

Inserts the locations from the other set, possibly overwriting the associated of data the locations already present.

a_set:insert(17, 42, "nothing")
b_set:insert(17, 42, "something")
a_set:union(b_set)
assert(a_set:get(17, 42) == "something")

location_set:inter

Deletes the locations that are not in the other set. Associated data is kept intact if not removed.

a_set:insert(17, 42, "nothing")
b_set:insert(17, 42, "something")
a_set:inter(b_set)
assert(a_set:get(17, 42) == "nothing")

location_set:iter

Calls the given function on all the locations of the set. Iteration order is not deterministic. If the order actually matters, the #location_set:stable_iter method should be used instead.

some_set:iter(function(x, y, data) wesnoth.message(string.format("[%d,%d] = %s", x, y, type(data))) end)

location_set:stable_iter

Calls the given function on all the locations of the set. Contrarily to #location_set:iter, the iteration is deterministic and hence safe for networks and replays.

some_set:stable_iter(function(x, y, data) wesnoth.message(string.format("[%d,%d] = %s", x, y, type(data))) end)

location_set:filter

Returns a new set containing all the locations of the set for which the given function returns true.

local new_set = old_set:filter(function(x, y, v)
  local d = helper.distance_between(a, b, x, y)
  return d <= 5 and v == "not found"
end)
wesnoth.message(string.format("%d traps in the neighborhood of (%d,%d)", new_set:size(), a, b))

location_set:union_merge

Calls the given function for all the locations of the other set and uses the returned values to fill the set. Note: the merge order is not stable.

-- merge the elements of s2 into s1 but preserve the old data of s1
function set_union(s1, s2)
    s1:union_merge(s2, function(x, y, v1, v2) return v1 or v2 end)
end
-- remove from s1 the elements of s2
function set_difference(s1, s2)
    -- the nested function is called s2:size() times; note: v2 is never nil
    s1:union_merge(s2, function(x, y, v1, v2) return nil end)
end

location_set:inter_merge

Calls the given function for all the locations of the set and uses the returned values to replace it. Note: the merge order is not stable.

-- compute the intersection of s1 and s2 and put it into s1, but overwrite the data of s1
function set_inter(s1, s2)
    s1:inter_merge(s2, function(x, y, v1, v2) return v2 or v1 end)
end
-- remove from s1 the elements of s2
function set_difference(s1, s2)
    -- the nested function is called s1:size() times; note: v1 is never nil
    s1:inter_merge(s2, function(x, y, v1, v2) return not v2 end)
end
This page was last edited on 12 February 2021, at 13:34.