Quantcast
Viewing all articles
Browse latest Browse all 12856

FractalWorld:DetermineXShift() Issues

I’ve posted about this issue before a while back: http://forums.civfanatics.com/showthread.php?t=470720

I’ve been getting a little more comfortable with Lua and I’ve recently been trying to adjust and correct this issue within a map script of mine. Shifting along the Y axis seems to work just fine; the land masses are usually centered (unless it's Pangaea, then I believe it's intentionally off center for more varied terrain instead of always having one big continent in the middle with jungle cutting it in half). It's the shifting along the X axis that has problems.

Here’s the existing function:
Spoiler:
Code:

function FractalWorld: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 land_totals = {};
        for x = 0, self.iNumPlotsX - 1 do
                local current_column = 0;
                for y = 0, self.iNumPlotsY - 1 do
                        local i = y * self.iNumPlotsX + x + 1;
                        if (self.plotTypes[i] ~= PlotTypes.PLOT_OCEAN) 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 = math.floor(self.iNumPlotsX / 10);
        -- Measure the groups.
        for column_index = 1, self.iNumPlotsX do
                local current_group_total = 0;
                for current_column = column_index - group_radius, column_index + group_radius do
                        local current_index = current_column % self.iNumPlotsX;
                        if current_index == 0 then -- Modulo of the last column will be zero; this repairs the issue.
                                current_index = self.iNumPlotsX;
                        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 = self.iNumPlotsY * (2 * 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 - 1;
        return x_shift;
end



I've tried different modifications to this function within my script, but none of them seem to work.

1) local group_radius = math.floor(self.iNumPlotsX / 10);
The default divisor is 10, for a total "group" column width of 20% the length of a map (8 + 8 = 16 tiles on a Standard 80 width map). This "should" work fine with maps like Continents with large spans of ocean, because if you took smaller group samples, your edge would favor the left and not really be centered. But, on scripts with many continents and snaky shapes, taking a sample this large will usually fail.

So, I tried using larger divisors (25+) so that the group column is thinner, but still no success. There were still some maps being shifted incorrectly when there was a clear column to base the edge off of.

2) I tried simply setting group_radius equal to 0 so that only a single column is used. Yes, this would create edges that favored the left side and are not centered, but I wanted to test it anyway. Still, even with this there were times that the edge sliced through land when there were visible columns of only ocean.

Though, I was a little wary of this method because I'm not sure if it messes with the "For" loop if I set group_radius = 0. "for current_column = column_index - group_radius, column_index + group_radius do" would basically be: "for current_column = column_index, column_index do" -- would that even run the loop if the start and end value are the same?

3) I then tried setting group_radius to a hard value of simply 1. This way, each group column would be the width of 3 columns. Still no luck.

4) I tried keeping the default loop and group radius, but edited the last part of the function which identifies the group with the least amount of land in it. I tried adding in an additional check which not only chooses the center column of the group with the least amount of land in it, but also checks to make sure the center column equals zero land. There were still times where it didn't work. I then tried a very low value check of <= math.ceil(self.iNumPlotsY / 20) in case of islands or small strips of land crossing through and still no luck.

Here's a simple diagram which shows part of the problem (using squares for clarity and only a group radius of 4) which is also described in the topmost comment of the function itself. One would think the obvious choice to base the edge on would be within Group A. But, the way the land tiles are totaled in groups, that isn't the case.

Image may be NSFW.
Clik here to view.


Here are some example of the script being ran. I photoshopped how the minimap should look and where the shifted edge should be and also the group column the script chose, which would be 10% of the map width on either side of the column line. Lands within the group are highlighted.

Image may be NSFW.
Clik here to view.


Image may be NSFW.
Clik here to view.


Image may be NSFW.
Clik here to view.


Image may be NSFW.
Clik here to view.


Examples A and B get screwed up because the places where it should shift the edge to are narrow columns of water with long strips of land running from north to south. C and D work out well because the water is a little wider and the land is broken-up more instead of being long walls of land on either side.

Is there a way to rewrite this function so that it accurately shifts the map for these types of map scripts?

Also, is there some kind of error in this function that could be causing problems sometimes (outside of the problem displayed in the diagram)? Because, even the examples in my older post a while back were shifted incorrectly and they had VERY clear ways of doing so: http://forums.civfanatics.com/showthread.php?t=470720 I'm not sure what the problem is with those; something's not right.

Viewing all articles
Browse latest Browse all 12856

Trending Articles