Ticket #1688: belgian_uplands2012-10-2.diff

File belgian_uplands2012-10-2.diff, 16.4 KB (added by FeXoR, 12 years ago)

The SVN .diff

  • binaries/data/mods/public/art/textures/ui/session/icons/mappreview/belgian_uplands.png

    Cannot display: file marked as a binary type.
    svn:mime-type = application/octet-stream
  • binaries/data/mods/public/maps/random/belgian_uplands.js

    Property changes on: binaries/data/mods/public/art/textures/ui/session/icons/mappreview/belgian_uplands.png
    ___________________________________________________________________
    Added: svn:mime-type
    ## -0,0 +1 ##
    +application/octet-stream
    \ No newline at end of property
     
     1RMS.LoadLibrary("rmgen");
     2
     3const BUILDING_ANGlE = -PI/4;
     4
     5// initialize map
     6
     7log("Initializing map...");
     8
     9InitMap();
     10
     11var numPlayers = getNumPlayers();
     12var mapSize = getMapSize();
     13
     14
     15//////////
     16// Heightmap functionality
     17//////////
     18
     19// Some heightmap variables
     20const MIN_HEIGHT = - SEA_LEVEL; // 20
     21const MAX_HEIGHT = 0xFFFF/HEIGHT_UNITS_PER_METRE - SEA_LEVEL; // A bit smaler than 90
     22
     23// Random heightmap generation
     24function getRandomReliefmap(minHeight, maxHeight)
     25{
     26    minHeight = (minHeight || MIN_HEIGHT);
     27    maxHeight = (maxHeight || MAX_HEIGHT);
     28    if (minHeight < MIN_HEIGHT)
     29        warn("getRandomReliefmap: Argument minHeight is smaler then the supported minimum height of " + MIN_HEIGHT + " (const MIN_HEIGHT): " + minHeight)
     30    if (maxHeight > MAX_HEIGHT)
     31        warn("getRandomReliefmap: Argument maxHeight is smaler then the supported maximum height of " + MAX_HEIGHT + " (const MAX_HEIGHT): " + maxHeight)
     32    var reliefmap = [];
     33    for (var x = 0; x <= mapSize; x++)
     34    {
     35        reliefmap.push([]);
     36        for (var y = 0; y <= mapSize; y++)
     37        {
     38            reliefmap[x].push(randFloat(minHeight, maxHeight));
     39        }
     40    }
     41    return reliefmap;
     42}
     43
     44// Apply a heightmap
     45function setReliefmap(reliefmap)
     46{
     47    // g_Map.height = reliefmap;
     48    for (var x = 0; x <= mapSize; x++)
     49    {
     50        for (var y = 0; y <= mapSize; y++)
     51        {
     52            setHeight(x, y, reliefmap[x][y]);
     53        }
     54    }
     55}
     56
     57// Get the diferrence between minimum and maxumum height
     58function getMinAndMaxHeight(reliefmap)
     59{
     60    var height = {};
     61    height.min = Infinity;
     62    height.max = -Infinity;
     63    for (var x = 0; x <= mapSize; x++)
     64    {
     65        for (var y = 0; y <= mapSize; y++)
     66        {
     67            if (reliefmap[x][y] < height.min)
     68                height.min = reliefmap[x][y];
     69            else if (reliefmap[x][y] > height.max)
     70                height.max = reliefmap[x][y];
     71        }
     72    }
     73    return height;
     74}
     75
     76// Normalizing the heightmap
     77function getRescaledReliefmap(reliefmap, minHeight, maxHeight)
     78{
     79    var newReliefmap = deepcopy(reliefmap);
     80    minHeight = (minHeight || MIN_HEIGHT);
     81    maxHeight = (maxHeight || MAX_HEIGHT);
     82    if (minHeight < MIN_HEIGHT)
     83        warn("getRescaledReliefmap: Argument minHeight is smaler then the supported minimum height of " + MIN_HEIGHT + " (const MIN_HEIGHT): " + minHeight)
     84    if (maxHeight > MAX_HEIGHT)
     85        warn("getRescaledReliefmap: Argument maxHeight is smaler then the supported maximum height of " + MAX_HEIGHT + " (const MAX_HEIGHT): " + maxHeight)
     86    var oldHeightRange = getMinAndMaxHeight(reliefmap);
     87    for (var x = 0; x <= mapSize; x++)
     88    {
     89        for (var y = 0; y <= mapSize; y++)
     90        {
     91            newReliefmap[x][y] = minHeight + (reliefmap[x][y] - oldHeightRange.min) / (oldHeightRange.max - oldHeightRange.min) * (maxHeight - minHeight);
     92        }
     93    }
     94    return newReliefmap
     95}
     96
     97// Applying decay errosion (terrain independent)
     98function getHeightErrosionedReliefmap(reliefmap, strength)
     99{
     100    var newReliefmap = deepcopy(reliefmap);
     101    strength = (strength || 1.0); // Values much higher then 1 (1.32+ for an 8 tile map, 1.45+ for a 12 tile map, 1.62+ @ 20 tile map, 0.99 @ 4 tiles) will result in a resonance disaster/self interference
     102    var map = [[1, 0], [1, 1], [0, 1], [-1, 1], [-1, 0], [-1, -1], [0, -1], [1, -1]]; // Default
     103    for (var x = 0; x <= mapSize; x++)
     104    {
     105        for (var y = 0; y <= mapSize; y++)
     106        {
     107            var div = 0;
     108            for (var i = 0; i < map.length; i++)
     109                newReliefmap[x][y] += strength / map.length * (reliefmap[(x + map[i][0] + mapSize + 1) % (mapSize + 1)][(y + map[i][1] + mapSize + 1) % (mapSize + 1)] - reliefmap[x][y]); // Not entirely sure if scaling with map.length is perfect but tested values seam to indicate it is
     110        }
     111    }
     112    return newReliefmap;
     113}
     114
     115//////////
     116// Apply hightmap munipulation
     117//////////
     118
     119// Set target min and max height depending on map size to make average stepness the same on all map sizes
     120var heightRange = {"min": MIN_HEIGHT * mapSize / 512, "max": MAX_HEIGHT * mapSize / 512};
     121
     122// Set average water coverage
     123var averageWaterCoverage = 1/3; // NOTE: Since errosion is not pedictable actual water coverage might vary much with the same values
     124if (mapSize < 200)
     125    averageWaterCoverage = 2/3 * averageWaterCoverage;
     126var waterHeight = -MIN_HEIGHT + heightRange.min + averageWaterCoverage * (heightRange.max - heightRange.min);
     127var waterHeightAdjusted = waterHeight + MIN_HEIGHT;
     128setWaterHeight(waterHeight);
     129
     130// Generate reliefmap
     131var myReliefmap = getRandomReliefmap(heightRange.min, heightRange.max);
     132for (var i = 0; i < 50 + mapSize/4; i++) // Cycles depend on used getHeightErrosionedReliefmap.map and mapSize so should be put inside getHeightErrosionedReliefmap
     133    myReliefmap = getHeightErrosionedReliefmap(myReliefmap, 1);
     134myReliefmap = getRescaledReliefmap(myReliefmap, heightRange.min, heightRange.max);
     135setReliefmap(myReliefmap);
     136
     137
     138//////////
     139// Apply terrain texture by height
     140//////////
     141
     142var textueByHeight = [];
     143textueByHeight.push({"upperHeightLimit": heightRange.min + 1/3 * (waterHeightAdjusted - heightRange.min), "terrein": "temp_sea_rocks"});
     144var terreins = ["temp_sea_weed"];
     145terreins = terreins.concat(terreins, terreins, terreins, terreins);
     146terreins = terreins.concat(terreins, terreins, terreins, terreins);
     147terreins.push("temp_sea_weed|gaia/fauna_fish");
     148textueByHeight.push({"upperHeightLimit": heightRange.min + 2/3 * (waterHeightAdjusted - heightRange.min), "terrein": terreins});
     149textueByHeight.push({"upperHeightLimit": heightRange.min + 3/3 * (waterHeightAdjusted - heightRange.min), "terrein": "temp_mud_a"});
     150var terreins = ["temp_plants_bog", "temp_plants_bog_aut", "temp_dirt_gravel_plants", "temp_grass_d"];
     151terreins = terreins.concat(terreins, terreins, terreins, terreins, terreins);
     152terreins = ["temp_plants_bog|gaia/flora_bush_temperate"].concat(terreins, terreins);
     153terreins = ["temp_dirt_gravel_plants|gaia/geology_metal_temperate", "temp_dirt_gravel_plants|gaia/geology_stone_temperate", "temp_plants_bog|gaia/fauna_rabbit"].concat(terreins, terreins);
     154terreins = ["temp_plants_bog_aut|gaia/flora_tree_dead"].concat(terreins, terreins);
     155textueByHeight.push({"upperHeightLimit": waterHeightAdjusted + 1/6 * (heightRange.max - waterHeightAdjusted), "terrein": terreins});
     156textueByHeight.push({"upperHeightLimit": waterHeightAdjusted + 2/6 * (heightRange.max - waterHeightAdjusted),
     157    "terrein": ["temp_grass", "temp_grass_d", "temp_grass_long_b", "temp_grass_plants"]});
     158textueByHeight.push({"upperHeightLimit": waterHeightAdjusted + 3/6 * (heightRange.max - waterHeightAdjusted),
     159    "terrein": ["temp_grass", "temp_grass_b", "temp_grass_c", "temp_grass_mossy"]});
     160textueByHeight.push({"upperHeightLimit": waterHeightAdjusted + 4/6 * (heightRange.max - waterHeightAdjusted),
     161    "terrein": ["temp_grass", "temp_grass_b", "temp_grass_c", "temp_grass_d", "temp_grass_long_b", "temp_grass_clovers_2", "temp_grass_mossy", "temp_grass_plants"]});
     162var terreins = ["temp_grass_plants|gaia/flora_tree_euro_beech", "temp_grass_mossy|gaia/flora_tree_poplar", "temp_grass_mossy|gaia/flora_tree_poplar_lombardy",
     163    "temp_grass_long|gaia/flora_bush_temperate", "temp_mud_plants|gaia/flora_bush_temperate", "temp_mud_plants|gaia/flora_bush_badlands",
     164    "temp_grass_long|gaia/flora_tree_apple", "temp_grass_clovers|gaia/flora_bush_berry", "temp_grass_clovers_2|gaia/flora_bush_grapes",
     165    "temp_grass_plants|gaia/fauna_deer", "temp_grass_long_b|gaia/fauna_rabbit"];
     166var numTerreins = terreins.length;
     167for (var i = 0; i < numTerreins; i++)
     168    terreins.push("temp_grass_plants");
     169textueByHeight.push({"upperHeightLimit": waterHeightAdjusted + 5/6 * (heightRange.max - waterHeightAdjusted), "terrein": terreins});
     170textueByHeight.push({"upperHeightLimit": waterHeightAdjusted + 6/6 * (heightRange.max - waterHeightAdjusted),
     171    "terrein": ["temp_grass_mossy|gaia/flora_tree_oak", "temp_forestfloor_pine|gaia/flora_tree_pine",
     172    "temp_grass_mossy|gaia/flora_tree_oak", "temp_forestfloor_pine|gaia/flora_tree_pine",
     173    "temp_mud_plants|gaia/flora_tree_dead", "temp_plants_bog|gaia/flora_tree_oak_large",
     174    "temp_dirt_gravel_plants|gaia/flora_tree_aleppo_pine", "temp_forestfloor_autumn|gaia/flora_tree_carob"]});
     175var minTerrainDistToBorder = 3;
     176for(var x = minTerrainDistToBorder; x < mapSize - minTerrainDistToBorder; x++)
     177{
     178    for (var y = minTerrainDistToBorder; y < mapSize - minTerrainDistToBorder; y++)
     179    {
     180        var textureMinHeight = heightRange.min;
     181        for (var i = 0; i < textueByHeight.length; i++)
     182        {
     183            if (getHeight(x, y) >= textureMinHeight && getHeight(x, y) <= textueByHeight[i].upperHeightLimit)
     184            {
     185                placeTerrain(x, y, textueByHeight[i].terrein);
     186                break;
     187            }
     188            else
     189            {
     190                textureMinHeight = textueByHeight[i].upperHeightLimit;
     191            }
     192        }
     193    }
     194}
     195
     196//////////
     197// Find good start positions
     198//////////
     199
     200var startPositions = [];
     201var possibleStartPositions = [];
     202var neededDistance = 7;
     203var distToBorder = 2 * neededDistance; // Has to be greater than neededDistance! Otherwise the check if low/high ground is near will fail...
     204var lowerHeightLimit = textueByHeight[3].upperHeightLimit;
     205var upperHeightLimit = textueByHeight[6].upperHeightLimit;
     206// Check for valid points by height
     207for (var x = distToBorder + minTerrainDistToBorder; x < mapSize - distToBorder - minTerrainDistToBorder; x++)
     208{
     209    for (var y = distToBorder + minTerrainDistToBorder; y < mapSize - distToBorder - minTerrainDistToBorder; y++)
     210    {
     211        var actualHeight = getHeight(x, y);
     212        if (actualHeight > lowerHeightLimit && actualHeight < upperHeightLimit)
     213        {
     214            // Check for points within a valid area by height (rectangular so not optimal fast)
     215            var isPossible = true;
     216            for (var offX = - neededDistance; offX <= neededDistance; offX++)
     217            {
     218                for (var offY = - neededDistance; offY <= neededDistance; offY++)
     219                {
     220                    var testHeight = getHeight(x + offX, y + offY);
     221                    if (testHeight <= lowerHeightLimit || testHeight >= upperHeightLimit)
     222                    {
     223                        isPossible = false;
     224                        break;
     225                    }
     226                }
     227            }
     228            if (isPossible)
     229            {
     230                possibleStartPositions.push([x, y]);
     231                // placeTerrain(x, y, "blue");
     232            }
     233        }
     234    }
     235}
     236
     237// Trying to reduce the number of possible start locations...
     238
     239// ...by beeing in a circle of mapSize / 2 distance to the center
     240var possibleStartPositionsTemp = [];
     241var maxDistToCenter = mapSize / 2;
     242for (var i = 0; i < possibleStartPositions.length; i++)
     243{
     244    var deltaX = possibleStartPositions[i][0] - mapSize / 2;
     245    var deltaY = possibleStartPositions[i][1] - mapSize / 2;
     246    var distToCenter = Math.pow(Math.pow(deltaX, 2) + Math.pow(deltaY, 2), 1/2);
     247    if (distToCenter < maxDistToCenter)
     248    {
     249        possibleStartPositionsTemp.push(deepcopy(possibleStartPositions[i]));
     250        // placeTerrain(possibleStartPositions[i][0], possibleStartPositions[i][1], "purple");
     251    }
     252}
     253possibleStartPositions = deepcopy(possibleStartPositionsTemp);
     254
     255// ...by checking if low and high ground is near. Rectangular check since faster...
     256var possibleStartPositionsTemp = [];
     257var maxDistToResources = distToBorder; // Has to be <= distToBorder!
     258var minNumLowTiles = 10;
     259var minNumHighTiles = 10;
     260for (var i = 0; i < possibleStartPositions.length; i++)
     261{
     262    var numLowTiles = 0;
     263    var numHighTiles = 0;
     264    for (var dx = - maxDistToResources; dx < maxDistToResources; dx++)
     265    {
     266        for (var dy = - maxDistToResources; dy < maxDistToResources; dy++)
     267        {
     268            var testHeight = getHeight(possibleStartPositions[i][0] + dx, possibleStartPositions[i][1] + dy);
     269            if (testHeight < lowerHeightLimit)
     270                numLowTiles++;
     271            if (testHeight > upperHeightLimit)
     272                numHighTiles++;
     273            if (numLowTiles > minNumLowTiles && numHighTiles > minNumHighTiles)
     274                break;
     275        }
     276        if (numLowTiles > minNumLowTiles && numHighTiles > minNumHighTiles)
     277            break;
     278    }
     279    if (numLowTiles > minNumLowTiles && numHighTiles > minNumHighTiles)
     280    {
     281        possibleStartPositionsTemp.push(deepcopy(possibleStartPositions[i]));
     282        // placeTerrain(possibleStartPositions[i][0], possibleStartPositions[i][1], "red");
     283    }
     284}
     285possibleStartPositions = deepcopy(possibleStartPositionsTemp);
     286
     287// Get some random start location derivations. NOTE: Itterating over all possible derivations is just to much (valid points ** numPlayers)
     288var maxTries = 100000; // floor(800000 / (Math.pow(numPlayers, 2) / 2));
     289
     290var possibleDerivations = [];
     291for (var i = 0; i < maxTries; i++)
     292{
     293    var vector = [];
     294    for (var p = 0; p < numPlayers; p++)
     295        vector.push(randInt(possibleStartPositions.length));
     296    possibleDerivations.push(vector);
     297}
     298
     299// Maximise minimum distance between start locations
     300var maxMinDist = 0;
     301for (var d = 0; d < possibleDerivations.length; d++)
     302{
     303    var minDist = 2 * mapSize;
     304    for (var p1 = 0; p1 < numPlayers - 1; p1++)
     305    {
     306        for (var p2 = p1 + 1; p2 < numPlayers; p2++)
     307        {
     308            if (p1 != p2)
     309            {
     310                var StartPositionP1 = deepcopy(possibleStartPositions[possibleDerivations[d][p1]]);
     311                var StartPositionP2 = deepcopy(possibleStartPositions[possibleDerivations[d][p2]]);
     312                var actualDist = Math.pow(Math.pow(StartPositionP1[0] - StartPositionP2[0], 2) + Math.pow(StartPositionP1[1] - StartPositionP2[1], 2), 1/2);
     313                if (actualDist < minDist)
     314                    minDist = deepcopy(actualDist);
     315                if (minDist < maxMinDist)
     316                    break;
     317            }
     318        }
     319        if (minDist < maxMinDist)
     320            break;
     321    }
     322    if (minDist > maxMinDist)
     323    {
     324        maxMinDist = deepcopy(minDist);
     325        var bestDerivation = deepcopy(possibleDerivations[d]);
     326    }
     327}
     328
     329// Place players
     330for (var p = 0; p < numPlayers; p++)
     331{
     332    var actualX = possibleStartPositions[bestDerivation[p]][0];
     333    var actualY = possibleStartPositions[bestDerivation[p]][1];
     334    placeCivDefaultEntities(actualX, actualY, p + 1, BUILDING_ANGlE, {"iberWall" : false});
     335    var uDist = 8;
     336    var uSpace = 1;
     337    for (var j = 1; j <= 4; ++j)
     338    {
     339        var uAngle = BUILDING_ANGlE - PI * (2-j) / 2;
     340        var count = 4;
     341        for (var numberofentities = 0; numberofentities < count; numberofentities++)
     342        {
     343            var ux = actualX + uDist * cos(uAngle) + numberofentities * uSpace * cos(uAngle + PI/2) - (0.75 * uSpace * floor(count / 2) * cos(uAngle + PI/2));
     344            var uz = actualY + uDist * sin(uAngle) + numberofentities * uSpace * sin(uAngle + PI/2) - (0.75 * uSpace * floor(count / 2) * sin(uAngle + PI/2));
     345            if (j % 2 == 0)
     346                placeObject(ux, uz, "gaia/flora_bush_berry", 0, randFloat(0, 2*PI));
     347            else
     348                placeObject(ux, uz, "gaia/flora_tree_cypress", 0, randFloat(0, 2*PI));
     349        }
     350    }
     351}
     352
     353
     354// Export map data
     355ExportMap();
  • binaries/data/mods/public/maps/random/belgian_uplands.json

     
     1{
     2    "settings" : {
     3        "Name" : "Belgian Uplands",
     4        "Script" : "belgian_uplands.js",
     5        "Description" : "An experimental map generated with erosion functionality. Players will seldomly be placed equally fair!",
     6        "CircularMap" : false,
     7        "BaseTerrain" : ["temp_grass", "temp_grass_b", "temp_grass_c", "temp_grass_d", "temp_grass_long_b", "temp_grass_clovers_2", "temp_grass_mossy", "temp_grass_plants"],
     8        "BaseHeight" : 0,
     9        "Preview" : "belgian_uplands.png",
     10        "XXXXXX" : "Optionally define other things here, like we would for a scenario"
     11    }
     12}