optimise [random_placement]
the cases distance=0 and distance = -1 now dont loop thougth all possible locations anymore when removing a used location.
This commit is contained in:
parent
2ba7ad5c43
commit
5de1d9b046
1 changed files with 32 additions and 32 deletions
|
@ -2,8 +2,6 @@ local helper = wesnoth.require "lua/helper.lua"
|
|||
local utils = wesnoth.require "lua/wml-utils.lua"
|
||||
|
||||
wesnoth.wml_actions.random_placement = function(cfg)
|
||||
local dist_le = nil
|
||||
|
||||
local parsed = helper.shallow_parsed(cfg)
|
||||
-- TODO: In most cases this tag is used to place units, so maybe make include_borders=no the default for [filter_location]?
|
||||
local filter = helper.get_child(parsed, "filter_location") or {}
|
||||
|
@ -13,34 +11,7 @@ wesnoth.wml_actions.random_placement = function(cfg)
|
|||
local variable = cfg.variable or helper.wml_error("[random_placement] missing required 'variable' attribute")
|
||||
local allow_less = cfg.allow_less == true
|
||||
local variable_previous = utils.start_var_scope(variable)
|
||||
|
||||
if distance < 0 then
|
||||
-- optimisation for distance = -1
|
||||
dist_le = function() return false end
|
||||
elseif distance == 0 then
|
||||
-- optimisation for distance = 0
|
||||
dist_le = function(x1,y1,x2,y2) return x1 == x2 and y1 == y2 end
|
||||
else
|
||||
-- optimisation: cloasure is faster than string lookups.
|
||||
local math_abs = math.abs
|
||||
-- same effect as helper.distance_between(x1,y1,x2,y2) <= distance but faster.
|
||||
dist_le = function(x1,y1,x2,y2)
|
||||
local d_x = math_abs(x1-x2)
|
||||
if d_x > distance then
|
||||
return false
|
||||
end
|
||||
if d_x % 2 ~= 0 then
|
||||
if x1 % 2 == 0 then
|
||||
y2 = y2 - 0.5
|
||||
else
|
||||
y2 = y2 + 0.5
|
||||
end
|
||||
end
|
||||
local d_y = math_abs(y1-y2)
|
||||
return d_x + 2*d_y <= 2*distance
|
||||
end
|
||||
end
|
||||
|
||||
local math_abs = math.abs
|
||||
local locs = wesnoth.get_locations(filter)
|
||||
if type(num_items) == "string" then
|
||||
num_items = math.floor(loadstring("local size = " .. #locs .. "; return " .. num_items)())
|
||||
|
@ -61,11 +32,40 @@ wesnoth.wml_actions.random_placement = function(cfg)
|
|||
wesnoth.set_variable(variable .. ".x", point[1])
|
||||
wesnoth.set_variable(variable .. ".y", point[2])
|
||||
wesnoth.set_variable(variable .. ".n", i)
|
||||
for j = size, 1, -1 do
|
||||
if dist_le(locs[j][1], locs[j][2], point[1], point[2]) then
|
||||
if distance < 0 then
|
||||
-- optimisation: nothing to do for distance < 0
|
||||
elseif distance == 0 then
|
||||
-- optimisation: for distance = 0 we just need to remove the element at index
|
||||
-- optimisation: swapping elements and storing size in an extra variable is faster than table.remove(locs, j)
|
||||
locs[index] = locs[size]
|
||||
size = size - 1
|
||||
else
|
||||
-- the default case and the main reason why this was implemented.
|
||||
for j = size, 1, -1 do
|
||||
local x1 = locs[j][1]
|
||||
local y1 = locs[j][2]
|
||||
local x2 = point[1]
|
||||
local y2 = point[2]
|
||||
-- optimisation: same effect as "if helper.distance_between(x1,y1,x2,y2) <= distance then goto continue; end" but faster.
|
||||
local d_x = math_abs(x1-x2)
|
||||
if d_x > distance then
|
||||
goto continue
|
||||
end
|
||||
if d_x % 2 ~= 0 then
|
||||
if x1 % 2 == 0 then
|
||||
y2 = y2 - 0.5
|
||||
else
|
||||
y2 = y2 + 0.5
|
||||
end
|
||||
end
|
||||
local d_y = math_abs(y1-y2)
|
||||
if d_x + 2*d_y > 2*distance then
|
||||
goto continue
|
||||
end
|
||||
-- optimisation: swapping elements and storing size in an extra variable is faster than table.remove(locs, j)
|
||||
locs[j] = locs[size]
|
||||
size = size - 1
|
||||
::continue::
|
||||
end
|
||||
end
|
||||
wesnoth.wml_actions.command (command)
|
||||
|
|
Loading…
Add table
Reference in a new issue