diff --git a/README.md b/README.md index a11d39a..cf1068a 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,5 @@ minetest-australopithecus-utils =============================== + +A util collection for Minetest mods. + diff --git a/utils/constants.lua b/utils/constants.lua new file mode 100644 index 0000000..f7ee6d1 --- /dev/null +++ b/utils/constants.lua @@ -0,0 +1,34 @@ +--[[ +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 constants. +constants = { + --- The size of one map block. Sometimes also called a chunk. By default + -- this constant has the value of 80. + block_size = 80 +} + diff --git a/utils/init.lua b/utils/init.lua new file mode 100644 index 0000000..e706626 --- /dev/null +++ b/utils/init.lua @@ -0,0 +1,40 @@ +--[[ +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. +--]] + + +-- Get the base path. +local base_path = minetest.get_modpath(minetest.get_current_modname()) + +-- Static utils +dofile(base_path .. "/constants.lua") +dofile(base_path .. "/mathutil.lua") +dofile(base_path .. "/tableutil.lua") + +-- Instance utils +dofile(base_path .. "/mapmanipulator.lua") +dofile(base_path .. "/noisemanager.lua") +dofile(base_path .. "/scatterer.lua") + diff --git a/utils/mapmanipulator.lua b/utils/mapmanipulator.lua new file mode 100644 index 0000000..1d8b6d5 --- /dev/null +++ b/utils/mapmanipulator.lua @@ -0,0 +1,89 @@ +--[[ +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. +--]] + + +--- The MapManipulator is a thin wrapper around the VoxelManip object +-- provided by minetest. It only capsules the VoxelManip and VoxelArea behind +-- a few functions so to minimize code. +MapManipulator = {} + + +--- Creates a new instance of MapManipulator. +-- +-- @return A new instance. +function MapManipulator:new() + local instance = { + area = nil, + emax = nil, + emin = nil, + voxelmanip = nil + } + + instance.voxelmanip, instance.emin, instance.emax = minetest.get_mapgen_object("voxelmanip") + instance.area = VoxelArea:new({ + MinEdge = instance.emin, + MaxEdge = instance.emax + }) + + setmetatable(instance, self) + self.__index = self + + return instance +end + + +-- Gets the VoxelArea for the current VoxelManip. +-- +-- @return The VoxelArea. +function MapManipulator:get_area() + return self.area +end + +--- Gets the data from the VoxelManip object. +-- The data is an array that can be accessed by using the VoxelArea object. +-- +-- @return The data. +function MapManipulator:get_data() + return self.voxelmanip:get_data() +end + +--- Sets the data into the VoxelManip object. +-- Will also correct and update the lighting, the liquids and flush the map. +-- +-- @param data The data to set. +function MapManipulator:set_data(data) + self.voxelmanip:set_data(data) + + self.voxelmanip:set_lighting({ + day = 1, + night = 0 + }) + self.voxelmanip:calc_lighting() + self.voxelmanip:update_liquids() + self.voxelmanip:write_to_map() + self.voxelmanip:update_map() +end + diff --git a/utils/mathutil.lua b/utils/mathutil.lua new file mode 100644 index 0000000..b3eb075 --- /dev/null +++ b/utils/mathutil.lua @@ -0,0 +1,144 @@ +--[[ +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 mathemtical functions. +mathutil = {} + + +--- Performs a linear transform on the given value to transform the value +-- from the range -10/10 to 0/1. +-- +-- @param value The value to transform. +-- @param new_min Optional. The minimum value for the new range, defaults to 0. +-- @param new_max Optional. The maximum value for the new range, defaults to 1. +-- @return The transformed value. +function mathutil.big_linear(value, new_min, new_max) + return mathutil.linear(value, -10, 10, new_min, new_max) +end + +--- Performs a linear transformation on the given value with the peak in center +-- of the min and max values. +-- +-- @param value The value to transform. +-- @param min Optional. The original minimum value, defaults to -1. +-- @param max Optional. The original maximum value, default to 1. +-- @param new_min Optional. The minimum value for the new range, defaults to 0. +-- @param new_max Optional. The maximum value for the new range, defaults to 1. +function mathutil.centered_linear(value, min, max, new_min, new_max) + min = min or -1 + max = max or 1 + + local center = (min + max) / 2 + + if value < center then + return mathutil.linear(value, min, center, new_min, new_max) + else + return mathutil.linear(value, max, center, new_min, new_max) + end +end + +--- Performs a cosine interpolation with the given offset between the given +-- min and max values. +-- +-- @param offset The offset to get, should be between 0 and 1. +-- @param min Optional. The minimum value of the range, defaults to 0. +-- @param max Optional. The maximum value of the range, defaults to 1. +-- @return The interpolated value at the given offset. +function mathutil.cosine(offset, min, max) + local value = (1 - math.cos(offset * math.pi)) / 2 + + if min ~= nil and max ~= nil then + return min * (1 - value) + max * value + else + return value + end +end + +--- Clamps one value to the given minimum/maximum values. Defaults to +-- 0 to 1 if min/max are omitted. +-- +-- @param value The value to clamp. +-- @param min Optional. The minimum value, defaults to 0. +-- @param max Optional. The masximum value, defaults to 1. +-- @return The value clamped to the given range. +function mathutil.clamp(value, min, max) + if min == nil or max == nil then + return math.min(math.max(value, -1), 1) + else + return math.min(math.max(value, min), max) + end +end + +--- Performs a linear transform on the given value to transform the value +-- from one range to another. +-- +-- @param value The value to transform. +-- @param min Optional. The original minimum value of the range, defaults to -1. +-- @param max Optional. The original maximum value of the range, defaults to 1. +-- @param new_min Optional. The minimum value for the new range, defaults to 0. +-- @param new_max Optional. The maximum value for the new range, defaults to 1. +-- @return The transformed value. +function mathutil.linear(value, min, max, new_min, new_max) + min = min or -1 + max = max or 1 + + if new_min == nil or new_max == nil then + return (value - min) / (max - min) + else + return (value - min) / (max - min) * (new_max - new_min) + new_min + end +end + +--- Gets the next lower prime from the given number. +-- +-- @param number The number. +-- @return The next lower prime. +function mathutil.next_lower_prime(number) + for lower = number, 0, -1 do + if (lower <= 2 or math.fmod(lower, 2) ~= 0) + and (lower <= 3 or math.fmod(lower, 3) ~= 0) + and (lower <= 5 or math.fmod(lower, 5) ~= 0) + and (lower <= 7 or math.fmod(lower, 7) ~= 0) then + + return lower + end + end + + return 0 +end + +--- Performs a linear transform on the given value to transform the value +-- from the range -1/1 to 0/1. +-- +-- @param value The value to transform. +-- @param new_min Optional. The minimum value for the new range, defaults to 0. +-- @param new_max Optional. The maximum value for the new range, defaults to 1. +-- @return The transformed value. +function mathutil.small_linear(value, new_min, new_max) + return mathutil.linear(value, -1, 1, new_min, new_max) +end + diff --git a/utils/noisemanager.lua b/utils/noisemanager.lua new file mode 100644 index 0000000..1d22394 --- /dev/null +++ b/utils/noisemanager.lua @@ -0,0 +1,111 @@ +--[[ +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. +--]] + + +--- The NoiseManager manages seeds and creates PRNG of various kinds, always +-- with a new, unique seed. The seed is incremented with each creation, so +-- it is guaranteed that the results are reproducable. +NoiseManager = {} + + +--- Creates a new instance of NoiseManager. +-- +-- @return A new instance of NoiseManager. +function NoiseManager:new() + local instance = { + map_size = { + x = 80, + y = 80, + z = 80 + }, + next_seed = 0 + } + + setmetatable(instance, self) + self.__index = self + + return instance +end + + +--- Creates a Perlin object with the given values. +-- +-- @param octaves The count of octaves. +-- @param persistence The persistence values. +-- @param scale The scale. +-- @return The new Perlin object. +function NoiseManager:get_noise(octaves, persistence, scale) + self.next_seed = self.next_seed + 1 + + return minetest.get_perlin(self.next_seed, octaves, persistence, scale) +end + +--- Creates a PerlinMap object with the given values. +-- +-- @param octaves The count of octaves. +-- @param persistence The persistence values. +-- @param scale The scale. +-- @param spreadx The spread of the x axis. +-- @param spready Optional. The spread of the y axis, defaults to spreadx. +-- @param spreadz Optional. The spread of the z axis, defaults to spreadx. +-- @param eased Optional. If to use eased noise, defaults to false. +-- @return The new PerlinMap object. +function NoiseManager:get_noise_map(octaves, persistence, scale, spreadx, spready, spreadz, eased) + self.next_seed = self.next_seed + 1 + + local parameters = { + offset = 0, + scale = scale, + spread = { + x = spreadx, + y = spready or spreadx, + z = spreadz or spreadx + }, + seed = self.next_seed, + octaves = octaves, + persist = persistence, + eased = eased + } + + return minetest.get_perlin_map(parameters, self.map_size) +end + +--- Gets the next seed that will be used. Does not increment the counter. +-- +-- @return The next seed that will be used. +function NoiseManager:get_next_seed() + return self.next_seed +end + +--- Creates a PseudoRandom object. +-- +-- @return The new PseudoRandom object. +function NoiseManager:get_random() + self.next_seed = self.next_seed + 1 + + return PseudoRandom:new(self.next_seed) +end + diff --git a/utils/scatterer.lua b/utils/scatterer.lua new file mode 100644 index 0000000..08ea5d1 --- /dev/null +++ b/utils/scatterer.lua @@ -0,0 +1,145 @@ +--[[ +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. +--]] + + +--- The Scatterer is a (simple) object that allows to scatter objects in +-- a 2D plane. +Scatterer = {} + + +function Scatterer:new() + local instance = { + height = 0, + items_counter = 0, + items = {}, + minx = 0, + miny = 0, + offset = 0, + scattered_items = nil, + source = nil, + width = 0 + } + + setmetatable(instance, self) + self.__index = self + + return instance +end + + +function Scatterer:check(origin_x, origin_y, item) + if item.min_distance == nil and item.max_distance == nil then + return true + end + + local distance = item.min_distance or 0 + if item.max_distance ~= nil then + distance = math.random(distance, item.max_distance) + end + + for x = origin_x - distance, origin_x + distance, 1 do + for y = origin_y - distance, origin_y + distance, 1 do + if x ~= origin_x or y ~= origin_y then + local index = noiseutil.index2d(x, y, self.width) + + if self.scattered_items[index] == item then + return false + end + end + end + end + + return true +end + +function Scatterer:get(x, y) + x = math.abs(x - self.minx) + y = math.abs(y - self.miny) + + return self.scattered_items[noiseutil.index2d(x, y, self.width) + self.offset] +end + +function Scatterer:get_item(x, y, value) + for idx = 0, self.items_counter - 1, 1 do + local item = self.items[idx] + if (item.threshold == nil or value >= item.threshold) + and (item.probability == nil or self:next_random_probability() <= item.probability) + and self:check(x, y, item) then + return item + end + end + + return nil +end + +function Scatterer:init(source, minx, miny, width, height, offset) + self.source = source + self.minx = minx or 0 + self.miny = miny or 0 + self.width = width or 112 + self.height = height or 112 + self.offset = offset or 0 + + self.scattered_items = {} + + local max_counter = self.width * self.height - 1 + + local numbers = {} + + for counter = self.offset, max_counter + self.offset, 1 do + numbers[counter] = counter + end + + for counter = self.offset, max_counter + self.offset, 1 do + local swap_index = math.random(counter, max_counter + self.offset) + + local temp = numbers[counter] + numbers[counter] = numbers[swap_index] + numbers[swap_index] = temp + + local number = numbers[counter] + local x = math.fmod(number, self.width) + local y = math.floor(number / self.width) + local index = noiseutil.index2d(x, y, self.width) + local value = 1 + + if self.source ~= nil then + value = self.source[index] + end + + self.scattered_items[index] = self:get_item(x, y, value) + end +end + +function Scatterer:next_random_probability() + return (10000 - math.random(0, 10000)) / 10000 +end + +function Scatterer:register(item) + self.items[self.items_counter] = item + self.items_counter = self.items_counter + 1 +end + diff --git a/utils/tableutil.lua b/utils/tableutil.lua new file mode 100644 index 0000000..76d6665 --- /dev/null +++ b/utils/tableutil.lua @@ -0,0 +1,51 @@ +--[[ +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 tables. +tableutil = {} + + +--- Reindexes the given 2d array/table, swapping the two dimensions. +-- +-- @param data The array/table 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 data. +function tableutil.swapped_reindex2d(data, new_x, new_y) + local reindexed_data = {} + + for old_x = 1, 80, 1 do + reindexed_data[new_x + old_x - 1] = {} + + for old_y = 1, 80, 1 do + reindexed_data[new_x + old_x - 1][new_y + old_y - 1] = data[old_y][old_x] + end + end + + return reindexed_data +end +