bc20045705
Now there wont be two "kingdoms_game"folders
387 lines
12 KiB
Lua
387 lines
12 KiB
Lua
--[[
|
|
Copyright (c) 2014, Robert 'Bobby' Zenz
|
|
All rights reserved.
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions are met:
|
|
|
|
* Redistributions of source code must retain the above copyright notice, this
|
|
list of conditions and the following disclaimer.
|
|
|
|
* Redistributions in binary form must reproduce the above copyright notice,
|
|
this list of conditions and the following disclaimer in the documentation
|
|
and/or other materials provided with the distribution.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
--]]
|
|
|
|
|
|
--- Various utility functions for working with arrays. An array is sub-form of
|
|
-- a array, the array is simply indexed with numbers like this:
|
|
--
|
|
-- local array = { 1 = "a", 2 = "b", 3 = "c" }
|
|
-- local array = { "a", "b", "c" }
|
|
arrayutil = {}
|
|
|
|
|
|
--- Gets if the given array contains the given item.
|
|
--
|
|
-- @param array The array to search in.
|
|
-- @param item The item to search for, can either be an item or another array.
|
|
-- @param equals Optional. The function to determine if items equal each other,
|
|
-- defaults to tableutil.equals.
|
|
-- @param offset_step Optional. If the given item is an array, this determines
|
|
-- how much of the array is skipped before it is tried to
|
|
-- match.
|
|
-- @return true if the array contains the given item.
|
|
function arrayutil.contains(array, item, equals, offset_step)
|
|
return arrayutil.index(array, item, equals, offset_step) >= 0
|
|
end
|
|
|
|
--- Creates a 2D array with the given bounds and sets it to the given default
|
|
-- value.
|
|
--
|
|
-- @param start_x The start of the first dimension, inclusive.
|
|
-- @param start_y The start of the second dimension, inclusive.
|
|
-- @param end_x The end of the first dimension, inclusive.
|
|
-- @param end_y The end of the second dimension, inclusive.
|
|
-- @param default_value The default value that will be set, it will be cloned
|
|
-- for every entry.
|
|
-- @return The created 2D array.
|
|
function arrayutil.create2d(start_x, start_y, end_x, end_y, default_value)
|
|
local array = {}
|
|
|
|
for x = start_x, end_x, 1 do
|
|
array[x] = {}
|
|
|
|
for y = start_y, end_y, 1 do
|
|
array[x][y] = tableutil.clone(default_value)
|
|
end
|
|
end
|
|
|
|
return array
|
|
end
|
|
|
|
--- Creates a 3D array with the given bounds and sets it to the given default
|
|
-- value.
|
|
--
|
|
-- @param start_x The start of the first dimension, inclusive.
|
|
-- @param start_y The start of the second dimension, inclusive.
|
|
-- @param start_z The start of the third dimension, inclusive.
|
|
-- @param end_x The end of the first dimension, inclusive.
|
|
-- @param end_y The end of the second dimension, inclusive.
|
|
-- @param end_z The end of the third dimension, inclusive.
|
|
-- @param default_value The default value that will be set, it will be cloned
|
|
-- for every entry.
|
|
-- @return The created 3D array.
|
|
function arrayutil.create3d(start_x, start_y, start_z, end_x, end_y, end_z, default_value)
|
|
local array = {}
|
|
|
|
for x = start_x, end_x, 1 do
|
|
array[x] = {}
|
|
|
|
for y = start_y, end_y, 1 do
|
|
array[x][y] = {}
|
|
|
|
for z = start_z, end_z, 1 do
|
|
array[x][y][z] = tableutil.clone(default_value)
|
|
end
|
|
end
|
|
end
|
|
|
|
return array
|
|
end
|
|
|
|
--- Gets the index of the item in the given array.
|
|
--
|
|
-- @param array The array to search in.
|
|
-- @param item The item to search for, can either be an item or another array.
|
|
-- @param equals Optional. The function to determine if items equal each other,
|
|
-- defaults to tableutil.equals.
|
|
-- @param offset_step Optional. If the given item is an array, this determines
|
|
-- how much of the array is skipped before it is tried to
|
|
-- match.
|
|
-- @return The index of the given item or array, -1 if it was not found.
|
|
function arrayutil.index(array, item, equals, offset_step)
|
|
equals = equals or tableutil.equals
|
|
offset_step = offset_step or 1
|
|
|
|
if #array == 0 then
|
|
return -1
|
|
end
|
|
|
|
local item_is_array = type(item) == "table"
|
|
|
|
if item_is_array then
|
|
if #array < #item then
|
|
return -1
|
|
end
|
|
end
|
|
|
|
if item_is_array then
|
|
for offset = 1, #array - 1, offset_step do
|
|
local match = true
|
|
|
|
for index = 1, #item, 1 do
|
|
local array_index = index + offset - 1
|
|
|
|
if array_index > #array then
|
|
array_index = array_index - #array
|
|
end
|
|
|
|
if not equals(array[array_index], item[index]) then
|
|
match = false
|
|
-- Ugly way to break a loop, I know.
|
|
index = #item + 1
|
|
end
|
|
end
|
|
|
|
if match then
|
|
return offset
|
|
end
|
|
end
|
|
else
|
|
for index = 1, #array, 1 do
|
|
if equals(array[index], item) then
|
|
return index
|
|
end
|
|
end
|
|
end
|
|
|
|
return -1
|
|
end
|
|
|
|
--- Finds the next matching column.
|
|
--
|
|
-- @param array The 2D array to search.
|
|
-- @param start_index Optional. The index at which to start. Defaults to 1, or
|
|
-- if the direction is reversed, the number of columns in
|
|
-- the array.
|
|
-- @param matcher Optional. The function that is used to determine if the column
|
|
-- matches or not. Is expected to take one argument, the item,
|
|
-- and return a boolean. The column matches if any of its items
|
|
-- matches this condition. Defaults to not nil and not empty
|
|
-- string.
|
|
-- @param reverse Optional. If the array should be serched backwards. Defaults
|
|
-- to false.
|
|
-- @return The index of the matching column. -1 if none was found.
|
|
function arrayutil.next_matching_column(array, start_index, matcher, reverse)
|
|
matcher = matcher or function(item)
|
|
return item ~= nil and item ~= ""
|
|
end
|
|
|
|
local current_column = 0
|
|
|
|
if reverse and start_index == nil then
|
|
for row_index = 1, #array, 1 do
|
|
local row = array[row_index]
|
|
|
|
current_column = math.max(current_column, #row)
|
|
end
|
|
else
|
|
current_column = start_index or 1
|
|
end
|
|
|
|
local had_column = true
|
|
|
|
while had_column do
|
|
had_column = false
|
|
|
|
for row_index = 1, #array, 1 do
|
|
local row = array[row_index]
|
|
|
|
if current_column >= 1 and current_column <= #row then
|
|
had_column = true
|
|
|
|
if matcher(row[current_column]) then
|
|
return current_column
|
|
end
|
|
end
|
|
end
|
|
|
|
if reverse then
|
|
current_column = current_column - 1
|
|
else
|
|
current_column = current_column + 1
|
|
end
|
|
end
|
|
|
|
return -1
|
|
end
|
|
|
|
--- Finds the next matching row.
|
|
--
|
|
-- @param array The 2D array to search.
|
|
-- @param start_index Optional. The index at which to start. Defaults to 1, or
|
|
-- if the direction is reversed, the number of rows in
|
|
-- the array.
|
|
-- @param matcher Optional. The function that is used to determine if the row
|
|
-- matches or not. Is expected to take one argument, the item,
|
|
-- and return a boolean. The row matches if any of its items
|
|
-- matches this condition. Defaults to not nil and not empty
|
|
-- string.
|
|
-- @param reverse Optional. If the array should be serched backwards. Defaults
|
|
-- to false.
|
|
-- @return The index of the matching row. -1 if none was found.
|
|
function arrayutil.next_matching_row(array, start_index, matcher, reverse)
|
|
matcher = matcher or function(item)
|
|
return item ~= nil and item ~= ""
|
|
end
|
|
|
|
local to = #array
|
|
local step = 1
|
|
|
|
if reverse then
|
|
start_index = start_index or #array
|
|
to = 1
|
|
step = -1
|
|
else
|
|
start_index = start_index or 1
|
|
end
|
|
|
|
for row_index = start_index, to, step do
|
|
local row = array[row_index]
|
|
|
|
for column_index = 1, #row, 1 do
|
|
if matcher(row[column_index]) then
|
|
return row_index
|
|
end
|
|
end
|
|
end
|
|
|
|
return -1
|
|
end
|
|
|
|
--- Finds the previous matching column.
|
|
--
|
|
-- @param array The 2D array to search.
|
|
-- @param start_index Optional. The index at which to start. Defaults to
|
|
-- the number columns in the array.
|
|
-- @param matcher Optional. The function that is used to determine if the column
|
|
-- matches or not. Is expected to take one argument, the item,
|
|
-- and return a boolean. The column matches if any of its items
|
|
-- matches this condition. Defaults to not nil and not empty
|
|
-- string.
|
|
-- @return The index of the matching column. -1 if none was found.
|
|
function arrayutil.previous_matching_column(array, start_index, matcher)
|
|
return arrayutil.next_matching_column(array, start_index, matcher, true)
|
|
end
|
|
|
|
--- Finds the previous matching row.
|
|
--
|
|
-- @param array The 2D array to search.
|
|
-- @param start_index Optional. The index at which to start. Defaults to
|
|
-- the number rows in the array.
|
|
-- @param matcher Optional. The function that is used to determine if the row
|
|
-- matches or not. Is expected to take one argument, the item,
|
|
-- and return a boolean. The row matches if any of its items
|
|
-- matches this condition. Defaults to not nil and not empty
|
|
-- string.
|
|
-- @return The index of the matching row. -1 if none was found.
|
|
function arrayutil.previous_matching_row(array, start_index, matcher)
|
|
return arrayutil.next_matching_row(array, start_index, matcher, true)
|
|
end
|
|
|
|
--- Removes empty rows and columns at the beginning and the end of the given
|
|
-- array.
|
|
--
|
|
-- @param array The array.
|
|
-- @param is_empty Optional. The function used for determining if the item is
|
|
-- empty. By default nil and an empty string is considered
|
|
-- empty. Expected is a function that takes one item and returns
|
|
-- a boolean.
|
|
function arrayutil.reduce2d(array, is_empty)
|
|
local first_row = arrayutil.next_matching_row(array, nil, is_empty)
|
|
local last_row = arrayutil.previous_matching_row(array, nil, is_empty)
|
|
|
|
local first_column = arrayutil.next_matching_column(array, nil, is_empty)
|
|
local last_column = arrayutil.previous_matching_column(array, nil, is_empty)
|
|
|
|
if last_row == -1 then
|
|
last_row = first_row
|
|
end
|
|
|
|
if last_column == -1 then
|
|
last_column = first_column
|
|
end
|
|
|
|
local reduced = {}
|
|
|
|
if first_row ~= -1 and first_column ~= -1 then
|
|
for row_index = first_row, last_row, 1 do
|
|
local row = array[row_index]
|
|
local reduced_row = {}
|
|
|
|
for column_index = first_column, last_column, 1 do
|
|
reduced_row[column_index - first_column + 1] = row[column_index]
|
|
end
|
|
|
|
reduced[row_index - first_row + 1] = reduced_row
|
|
end
|
|
end
|
|
|
|
return reduced
|
|
end
|
|
|
|
--- Reindexes the given 2D array, swapping the two dimensions.
|
|
--
|
|
-- @param data The array to reindex.
|
|
-- @param new_x The new startpoint for the first dimension.
|
|
-- @param new_y The new startpoint for the second dimension.
|
|
-- @return The reindexed array.
|
|
function arrayutil.swapped_reindex2d(data, new_x, new_y)
|
|
local reindexed_data = {}
|
|
|
|
for old_x = 1, constants.block_size, 1 do
|
|
local index_x = new_x + old_x - 1
|
|
reindexed_data[index_x] = {}
|
|
|
|
for old_y = 1, constants.block_size, 1 do
|
|
local index_y = new_y + old_y - 1
|
|
|
|
reindexed_data[index_x][index_y] = data[old_y][old_x]
|
|
end
|
|
end
|
|
|
|
return reindexed_data
|
|
end
|
|
|
|
--- Reindexes the given 3d array, swapping the two dimensions.
|
|
--
|
|
-- @param data The array to reindex.
|
|
-- @param new_x The new startpoint for the first dimension.
|
|
-- @param new_y The new startpoint for the second dimension.
|
|
-- @param new_z The new startpoint for the third dimension.
|
|
-- @return The reindexed array.
|
|
function arrayutil.swapped_reindex3d(data, new_x, new_y, new_z)
|
|
local reindexed_data = {}
|
|
|
|
for old_x = 1, constants.block_size, 1 do
|
|
local index_x = new_x + old_x - 1
|
|
reindexed_data[index_x] = {}
|
|
|
|
for old_z = 1, constants.block_size, 1 do
|
|
local index_z = new_z + old_z - 1
|
|
reindexed_data[index_x][index_z] = {}
|
|
|
|
for old_y = 1, constants.block_size, 1 do
|
|
local index_y = new_y + old_y - 1
|
|
|
|
reindexed_data[index_x][index_z][index_y] = data[old_z][old_y][old_x]
|
|
end
|
|
end
|
|
end
|
|
|
|
return reindexed_data
|
|
end
|
|
|