move set_variable.rand's logic to helper.rand

This commit is contained in:
Bär Halberkamp 2016-07-19 13:48:02 -04:00
parent 34d78f2a2a
commit 1d8d843a80
2 changed files with 85 additions and 75 deletions

View file

@ -380,10 +380,82 @@ function helper.shallow_parsed(cfg)
end
function helper.rand (possible_values)
wml_actions.set_variable({ name = "LUA_rand", rand = possible_values })
local result = wesnoth.get_variable("LUA_rand")
wesnoth.set_variable("LUA_rand")
return result
assert(type(possible_values) == "table" or type(possible_values) == "string", string.format("helper.rand expects a string or table as parameter, got %s instead", type(possible_values)))
local items = {}
local num_choices = 0
if type(possible_values) == "string" then
-- split on commas
for word in possible_values:gmatch("[^,]+") do
-- does the word contain two dots? If yes, that's a range
local dots_start, dots_end = word:find("%.%.")
if dots_start then
-- split on the dots if so and cast as numbers
local low = tonumber(word:sub(1, dots_start-1))
local high = tonumber(word:sub(dots_end+1))
-- perhaps someone passed a string as part of the range, intercept the issue
if not (low and high) then
wesnoth.message("Malformed range: " .. possible_values)
table.insert(items, word)
num_choices = num_choices + 1
else
if low > high then
-- low is greater than high, swap them
low, high = high, low
end
-- if both ends represent the same number, then just use that number
if low == high then
table.insert(items, low)
num_choices = num_choices + 1
else
-- insert a table representing the range
table.insert(items, {low, high})
-- how many items does the range contain? Increase difference by 1 because we include both ends
num_choices = num_choices + (high - low) + 1
end
end
else
-- handle as a string
table.insert(items, word)
num_choices = num_choices + 1
end
end
else
num_choices = #possible_values
items = possible_values
-- We need to parse ranges separately anyway
for i, val in ipairs(possible_values) do
if type(val) == "table" then
assert(#val == 2 and type(val[1]) == "number" and type(val[2]) == "number", "Malformed range for helper.rand")
if val[1] > val[2] then
val = {val[2], val[1]}
end
num_choices = num_choices + (val[2] - val[1])
end
end
end
local idx = wesnoth.random(1, num_choices)
for i, item in ipairs(items) do
if type(item) == "table" then -- that's a range
local elems = item[2] - item[1] + 1 -- amount of elements in the range, both ends included
if elems >= idx then
return item[1] + elems - idx
else
idx = idx - elems
end
else -- that's a single element
idx = idx - 1
if idx == 0 then
return item
end
end
end
return nil
end
function helper.deprecate(msg, f)

View file

@ -38,7 +38,7 @@ function wml_actions.sync_variable(cfg)
local variable_type = string.sub(name, string.len(name)) == "]" and "indexed" or ( wesnoth.get_variable(name .. ".length") > 0 and "array" or "attribute")
local variable_info = { name = name, type = variable_type }
table.insert(res, { "variable", variable_info })
if variable_type == "indexed" then
if variable_type == "indexed" then
table.insert(variable_info, { "value", wesnoth.get_variable(name) } )
elseif variable_type == "array" then
for i = 1, wesnoth.get_variable(name .. ".length") do
@ -53,7 +53,7 @@ function wml_actions.sync_variable(cfg)
)
for variable in helper.child_range(result, "variable") do
local name = variable.name
if variable.type == "indexed" then
wesnoth.set_variable(name, variable[1][2])
elseif variable.type == "array" then
@ -269,7 +269,7 @@ end
-- This is mainly for use in unit test macros, but maybe it can be useful elsewhere too
function wml_actions.test_condition(cfg)
local logger = cfg.logger or "warning"
-- This function returns true if it managed to explain the failure
local function explain(current_cfg, expect)
for i,t in ipairs(current_cfg) do
@ -313,7 +313,7 @@ function wml_actions.test_condition(cfg)
end
end
end
-- Use not twice here to convert nil to false
explain(cfg, not not cfg.result)
end
@ -398,7 +398,7 @@ function wml_actions.store_unit(cfg)
--cache the needed units here, since the filter might reference the to-be-cleared variable(s)
local units = wesnoth.get_units(filter)
local recall_units = wesnoth.get_recall_units(filter)
local writer = utils.vwriter.init(cfg, "unit")
for i,u in ipairs(units) do
@ -687,7 +687,7 @@ end
-- This is the port of the old [modify_ai] into lua. It is different from wesnoth.modify_ai in that it uses a standard side filter.
-- I don't know why these functions were made to behave differently, but this seems to be the more powerful and useful one according
-- to mattsc's comments
-- to mattsc's comments
function wml_actions.modify_ai(cfg)
wesnoth.modify_ai_wml(cfg)
end
@ -764,7 +764,7 @@ end
function wml_actions.put_to_recall_list(cfg)
local units = wesnoth.get_units(cfg)
for i, unit in ipairs(units) do
for i, unit in ipairs(units) do
if cfg.heal then
unit.hitpoints = unit.max_hitpoints
unit.moves = unit.max_moves
@ -990,7 +990,7 @@ wml_actions.unstore_unit = function(cfg)
if unit_cfg.gender == "female" then
text = cfg.female_text or cfg.text
else
text = cfg.male_text or cfg.text
text = cfg.male_text or cfg.text
end
local color = cfg.color
if color == nil and cfg.red and cfg.blue and cfg.green then
@ -1138,69 +1138,7 @@ function wml_actions.set_variable(cfg)
end
if cfg.rand then
local random_string = tostring(cfg.rand)
local num_choices = 0
local items = {}
-- split on commas
for word in random_string:gmatch("[^,]+") do
-- does the word contain two dots? If yes, that's a range
local dots_start, dots_end = word:find("%.%.")
if dots_start then
-- split on the dots if so and cast as numbers
local low = tonumber(word:sub(1, dots_start-1))
local high = tonumber(word:sub(dots_end+1))
-- perhaps someone passed a string as part of the range, intercept the issue
if not (low and high) then
wesnoth.message("<WML>","Malformed range: rand " .. cfg.rand)
table.insert(items, word)
num_choices = num_choices + 1
else
if low > high then
-- low is greater than high, swap them
low, high = high, low
end
-- if both ends represent the same number, then just use that number
if low == high then
table.insert(items, low)
num_choices = num_choices + 1
else
-- insert a table representing the range
table.insert(items, {low, high})
-- how many items does the range contain? Increase difference by 1 because we include both ends
num_choices = num_choices + (high - low) + 1
end
end
else
-- handle as a string
table.insert(items, word)
num_choices = num_choices + 1
end
end
local idx = wesnoth.random(1, num_choices)
local done = false
for i, item in ipairs(items) do
if type(item) == "table" then -- that's a range
local elems = item[2] - item[1] + 1 -- amount of elements in the range, both ends included
if elems >= idx then
wesnoth.set_variable(name, item[1] + elems - idx)
done = true
break
else
idx = idx - elems
end
else -- that's a single element
idx = idx - 1
if idx == 0 then
wesnoth.set_variable(name, item)
done = true
end
end
if done then break end
end
wesnoth.set_variable(name, helper.rand(tostring(cfg.rand)))
end
local join_child = helper.get_child(cfg, "join")