Skip to content

Commit

Permalink
Add a utility function to extract a location from the front of a vari…
Browse files Browse the repository at this point in the history
…adic parameter pack

The purpose of this is to make it easy for functions implemented in Lua to handle locations
in the same way as functions implemented in C++.

The location_set module has been updated to make use of this functionality in its setter functions.

Usage example:

Imagine a function foo with the following signature:

foo(bar : string, home : location, mode : string, target : location, moo : boolean) -> boolean

With the new read_location function 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.mP.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
  • Loading branch information
CelticMinstrel committed Feb 28, 2021
1 parent dacd5b3 commit 51cf262
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 6 deletions.
17 changes: 17 additions & 0 deletions data/lua/core/map.lua
Expand Up @@ -5,6 +5,23 @@ function wesnoth.map.split_terrain_code(code)
return table.unpack(code:split('^', {remove_empty = false}))
end

function wesnoth.map.read_location(...)
local x, y = ...
if y == nil then
if type(x.x) == 'number' and type(x.y) == 'number' then
x, y = x.x, x.y
elseif type(x[1]) == 'number' and type(x[2]) == 'number' then
x, y = table.unpack(x)
else
return nil, 0
end
return {x = x, y = y}, 1
elseif type(x) == 'number' or type(y) == 'number' then
return {x = x, y = y}, 2
end
return nil, 0
end

if wesnoth.kernel_type() ~= "Application Lua Kernel" then
-- possible terrain string inputs:
-- A A^ A^B ^ ^B
Expand Down
16 changes: 10 additions & 6 deletions data/lua/location_set.lua
Expand Up @@ -84,16 +84,20 @@ function methods:clear()
self.values = {}
end

function methods:get(x, y)
return self.values[index(x, y)]
function methods:get(...)
local loc = wesnoth.map.read_location(...)
return self.values[index(loc.x, loc.y)]
end

function methods:insert(x, y, v)
self.values[index(x, y)] = v or true
function methods:insert(...)
local loc, n = wesnoth.map.read_location(...)
local v = select(n + 1, ...)
self.values[index(loc.x, loc.y)] = v or true
end

function methods:remove(x, y)
self.values[index(x, y)] = nil
function methods:remove(...)
local loc = wesnoth.map.read_location(...)
self.values[index(loc.x, loc.y)] = nil
end

function methods:clone()
Expand Down

0 comments on commit 51cf262

Please sign in to comment.