-------------------------------------------------------------------------------------------
--ShiftMap Class
-------------------------------------------------------------------------------------------
function ShiftMaps()
--local stripRadius = self.stripRadius;
local shift_x = 0;
local shift_y = 0;
shift_x = DetermineXShift();
ShiftMapsBy(shift_x, shift_y);
end
-------------------------------------------------------------------------------------------
function ShiftMapsBy(xshift, yshift)
local W, H = Map.GetGridSize();
if(xshift > 0 or yshift > 0) then
local Shift = {}
local iDestI = 0
for iDestY = 0, H-1 do
for iDestX = 0, W-1 do
local iSourceX = (iDestX + xshift) % W;
--local iSourceY = (iDestY + yshift) % H; -- If using yshift, enable this and comment out the faster line below. - Bobert13
local iSourceY = iDestY
local iSourceI = W * iSourceY + iSourceX
Shift[iDestI] = elevationMap.data[iSourceI]
--print(string.format("Shift:%d, %f | eMap:%d, %f",iDestI,Shift[iDestI],iSourceI,elevationMap.data[iSourceI]))
iDestI = iDestI + 1
end
end
elevationMap.data = Shift --It's faster to do one large table operation here than it is to do thousands of small operations to set up a copy of the input table at the beginning. -Bobert13
end
return elevationMap
end
-------------------------------------------------------------------------------------------
function DetermineXShift()
--[[ This function will align the most water-heavy vertical portion of the map with the
vertical map edge. This is a form of centering the landmasses, but it emphasizes the
edge not the middle. If there are columns completely empty of land, these will tend to
be chosen as the new map edge, but it is possible for a narrow column between two large
continents to be passed over in favor of the thinnest section of a continent, because
the operation looks at a group of columns not just a single column, then picks the
center of the most water heavy group of columns to be the new vertical map edge. ]]--
-- First loop through the map columns and record land plots in each column.
local gridWidth, gridHeight = Map.GetGridSize();
local land_totals = {};
for x = 0, gridWidth - 1 do
local current_column = 0;
for y = 0, gridHeight - 1 do
local i = y * gridWidth + x + 1;
if not elevationMap:IsBelowSeaLevel(x,y) then
current_column = current_column + 1;
end
end
table.insert(land_totals, current_column);
end
-- Now evaluate column groups, each record applying to the center column of the group.
local column_groups = {};
-- Determine the group size in relation to map width.
local group_radius = 3;
-- Measure the groups.
for column_index = 1, gridWidth do
local current_group_total = 0;
--for current_column = column_index - group_radius, column_index + group_radius do
--Changed how group_radius works to get groups of four. -Bobert13
for current_column = column_index, column_index + group_radius do
local current_index = current_column % gridWidth;
if current_index == 0 then -- Modulo of the last column will be zero; this repairs the issue.
current_index = gridWidth;
end
current_group_total = current_group_total + land_totals[current_index];
end
table.insert(column_groups, current_group_total);
end
-- Identify the group with the least amount of land in it.
local best_value = gridHeight * (group_radius + 1); -- Set initial value to max possible.
local best_group = 1; -- Set initial best group as current map edge.
for column_index, group_land_plots in ipairs(column_groups) do
if group_land_plots < best_value then
best_value = group_land_plots;
best_group = column_index;
end
end
-- Determine X Shift
local x_shift = best_group + 2;
return x_shift;
end
------------------------------------------------------------------------------
--DiffMap Class
------------------------------------------------------------------------------
--Seperated this from GeneratePlotTypes() to use it in other functions. -Bobert13
DiffMap = inheritsFrom(FloatMap)
function GenerateDiffMap(width,height,xWrap,yWrap)
DiffMap = FloatMap:New(width,height,xWrap,yWrap)
local i = 0
for y = 0, height - 1,1 do
for x = 0,width - 1,1 do
if elevationMap:IsBelowSeaLevel(x,y) then
DiffMap.data[i] = 0.0
else
DiffMap.data[i] = GetDifferenceAroundHex(x,y)
end
i=i+1
end
end
DiffMap:Normalize()
i = 0
for y = 0, height - 1,1 do
for x = 0,width - 1,1 do
if elevationMap:IsBelowSeaLevel(x,y) then
DiffMap.data[i] = 0.0
else
DiffMap.data[i] = DiffMap.data[i] + elevationMap.data[i] * 1.1
end
i=i+1
end
end
DiffMap:Normalize()
return DiffMap
end
-------------------------------------------------------------------------------------------
function GeneratePlotTypes()
print("Creating initial map data - PerfectWorld3")
local gridWidth, gridHeight = Map.GetGridSize();
--first do all the preliminary calculations in this function
print(string.format("map size: width=%d, height=%d",gridWidth,gridHeight))
mc = MapConstants:New()
PWRandSeed()
elevationMap = GenerateElevationMap(gridWidth,gridHeight,true,false)
--elevationMap:Save("elevationMap.csv")
FillInLakes()
--now gen plot types
print("Generating plot types - PerfectWorld3")
ShiftMaps();
DiffMap = GenerateDiffMap(gridWidth,gridHeight,true,false);
rainfallMap, temperatureMap = GenerateRainfallMap(elevationMap)
--rainfallMap:Save("rainfallMap.csv")
riverMap = RiverMap:New(elevationMap)
riverMap:SetJunctionAltitudes()
riverMap:SiltifyLakes()
riverMap:SetFlowDestinations()
riverMap:SetRiverSizes(rainfallMap)
--find exact thresholds
local hillsThreshold = DiffMap:FindThresholdFromPercent(mc.hillsPercent,false,true)
local mountainsThreshold = DiffMap:FindThresholdFromPercent(mc.mountainsPercent,false,true)
local i = 0
for y = 0, gridHeight - 1,1 do
for x = 0,gridWidth - 1,1 do
local plot = Map.GetPlot(x,y);
if elevationMap:IsBelowSeaLevel(x,y) then
plot:SetPlotType(PlotTypes.PLOT_OCEAN, false, false)
elseif DiffMap.data[i] < hillsThreshold then
plot:SetPlotType(PlotTypes.PLOT_LAND,false,false)
--This code makes the game only ever plot flat land if it's within two tiles of
--the seam. This prevents issues with tiles that don't look like what they are.
elseif x == 0 or x == 1 or x == gridWidth - 1 or x == gridWidth -2 then
plot:SetPlotType(PlotTypes.PLOT_LAND,false,false)
-- Bobert13
elseif DiffMap.data[i] < mountainsThreshold then
plot:SetPlotType(PlotTypes.PLOT_HILLS,false,false)
else
plot:SetPlotType(PlotTypes.PLOT_MOUNTAIN,false,false)
end
i=i+1
end
end
GenerateCoasts();
end
------------------------------------------------------------------------------