Ticket #4275: optimize_caledonian_meadows2016_10_9c.patch

File optimize_caledonian_meadows2016_10_9c.patch, 14.8 KB (added by FeXoR, 8 years ago)

Some code cleanup

  • binaries/data/mods/public/maps/random/caledonian_meadows.js

     
    142142
    143143/**
    144144 * Drags a path to a target height smoothing it at the edges and return some points along the path.
    145  *
    146  * TODO:
    147  * Would be nice to tell the function what to do and how often in the arguments
    148  * Adding painted tiles to a tile class
    149145 */
    150 function placeRandomPathToHeight(start, pathTexture, target, targetHeight, width = 10, occurrence = 2, strength = 0.1, heightmap = g_Map.height)
     146function placeRandomPathToHeight(
     147    start, target, targetHeight, tileClass = undefined, texture = "road_rome_a",
     148    width = 10, distance = 4, strength = 0.08, heightmap = g_Map.height)
    151149{
    152     if (pathTexture === true)
    153         pathTexture = ['temp_road', "temp_road_overgrown", 'temp_grass_b'];
    154    
    155     let clTempPath = createTileClass();
    156     let targetReached = false;
     150    let pathPoints = [];
    157151    let position = deepcopy(start);
    158     while (!targetReached)
     152    while (true)
    159153    {
    160154        rectangularSmoothToHeight(position, width, width, targetHeight, strength, heightmap);
    161         if (pathTexture)
    162             createArea(new ClumpPlacer(0.2 * width * width, 1, 1, 1, floor(position.x), floor(position.y)), [new TerrainPainter(pathTexture), paintClass(clTempPath)]);
    163        
    164         // Set lets for next loop
     155        if (texture)
     156        {
     157            if (tileClass !== undefined)
     158                createArea(new ClumpPlacer(0.3 * width * width, 1, 1, 1, floor(position.x), floor(position.y)),
     159                    [new TerrainPainter(texture), paintClass(tileClass)]);
     160            else
     161                createArea(new ClumpPlacer(0.3 * width * width, 1, 1, 1, floor(position.x), floor(position.y)),
     162                    new TerrainPainter(texture));
     163        }
     164        pathPoints.push({ "x": position.x, "y": position.y, "dist": distance });
     165        // Check for distance to target and setup for next loop if needed
     166        if (getDistance(position.x, position.y, target.x, target.y) < distance / 2)
     167            break;
    165168        let angleToTarget = getAngle(position.x, position.y, target.x, target.y);
    166169        let angleOff = PI * (randFloat() - 0.5);
    167         position.x += occurrence * cos(angleToTarget + angleOff);
    168         position.y += occurrence * sin(angleToTarget + angleOff);
    169         if (getDistance(position.x, position.y, target.x, target.y) < occurrence / 2)
    170             targetReached = true;
     170        position.x += distance * cos(angleToTarget + angleOff);
     171        position.y += distance * sin(angleToTarget + angleOff);
    171172    }
    172     return clTempPath;
     173    return pathPoints;
    173174}
    174175
    175176function getGrad(wrapped = true, scalarField = g_Map.height)
     
    240241/**
    241242 * Meant to place e.g. resource spots within a height range
    242243 * @param {array} [heightRange] - The height range in which to place the entities (An associative array with keys "min" and "max" each containing a float)
    243  * @param {array} [avoidPoints] - An array of objects of the form {"x": int, "y": int, "dist": int}, points that will be avoided in the given dist e.g. start locations
    244  * @param {array} [avoidArea] - List of tiles to avoid
     244 * @param {array} [avoidPoints=[]] - An array of objects of the form {"x": int, "y": int, "dist": int}, points that will be avoided in the given dist e.g. start locations
     245 * @param {object} [avoidClass=undefined] - TileClass to be avoided
    245246 * @param {integer} [minDistance=30] - How many tile widths the entities to place have to be away from each other, start locations and the map border
    246247 * @param {array} [heightmap=g_Map.height] - The reliefmap the entities should be distributed on
    247  * @param {integer} [maxTries=1000] - How often random player distributions are rolled to be compared
     248 * @param {integer} [maxTries=2 * g_Map.size] - How often random player distributions are rolled to be compared (256 to 1024)
    248249 * @param {boolean} [isCircular=g_MapSettings.CircularMap] - If the map is circular or rectangular
    249250 */
    250 function getPointsByHeight(heightRange, avoidPoints, avoidArea, minDistance = 20, maxTries = 1000, heightmap = g_Map.height, isCircular = g_MapSettings.CircularMap)
     251function getPointsByHeight(heightRange, avoidPoints = [], avoidClass = undefined, minDistance = 20, maxTries = 2 * g_Map.size, heightmap = g_Map.height, isCircular = g_MapSettings.CircularMap)
    251252{
    252253    let points = [];
    253254    let placements = deepcopy(avoidPoints);
    254255    let validVertices = [];
    255256    let r = 0.5 * (heightmap.length - 1); // Map center x/y as well as radius
     257
    256258    for (let x = minDistance; x < heightmap.length - minDistance; ++x)
    257259    {
    258260        for (let y = minDistance; y < heightmap[0].length - minDistance; ++y)
    259261        {
    260             let isValid = true;
    261             for (let i = 0; i < pathArea.length; ++i)
    262                 if (pathArea[i].x == x && pathArea[i].y == y)
    263                     isValid = false;
    264             if (!isValid)
     262            if (avoidClass !== undefined && // Avoid adjecting tiles in avoidClass
     263                (g_Map.tileClasses[avoidClass].inclusionCount[max(x - 1, 0)][y] > 0 ||
     264                g_Map.tileClasses[avoidClass].inclusionCount[x][max(y - 1, 0)] > 0 ||
     265                g_Map.tileClasses[avoidClass].inclusionCount[min(x + 1, g_Map.tileClasses[avoidClass].inclusionCount.length - 1)][y] > 0 ||
     266                g_Map.tileClasses[avoidClass].inclusionCount[x][min(y + 1, g_Map.tileClasses[avoidClass].inclusionCount[0].length - 1)] > 0)
     267            )
    265268                continue;
    266            
    267             if (heightmap[x][y] > heightRange.min && heightmap[x][y] < heightRange.max && (!isCircular || r - getDistance(x, y, r, r) >= minDistance)) // Has correct height and enough distance to map border
     269
     270            if (heightmap[x][y] > heightRange.min && heightmap[x][y] < heightRange.max && // Has correct height
     271                (!isCircular || r - getDistance(x, y, r, r) >= minDistance)) // Enough distance to map border
    268272                validVertices.push({ "x": x, "y": y , "dist": minDistance});
    269273        }
    270274    }
    271    
     275
    272276    for (let tries = 0; tries < maxTries; ++tries)
    273277    {
    274278        let point = validVertices[randInt(validVertices.length)];
     
    277281            points.push(point);
    278282            placements.push(point);
    279283        }
     284        if ((tries != 0) && (tries % 100 == 0)) // Time Check
     285            log(points.length + " points found after " + tries + " tries after " + ((new Date().getTime() - genStartTime) / 1000) + "s");
    280286    }
    281    
     287
    282288    return points;
    283289}
    284290
     
    294300    "actor|props/flora/bush.xml", "actor|props/flora/bush_dry_a.xml", "actor|props/flora/bush_highlands.xml",
    295301    "actor|props/flora/bush_tempe_a.xml", "actor|props/flora/bush_tempe_b.xml", "actor|props/flora/ferns.xml"
    296302];
    297 
    298303function placeMine(point, centerEntity)
    299304{
    300305    placeObject(point.x, point.y, centerEntity, 0, randFloat(0, TWO_PI));
     
    334339    fences.push(new Fortress("fence", deepcopy(fences[i].wall).reverse()));
    335340
    336341// Groves, only Wood
    337 let groveEntities = [
    338     "gaia/flora_bush_temperate", "gaia/flora_tree_euro_beech"
    339 ];
     342let groveEntities = ["gaia/flora_bush_temperate", "gaia/flora_tree_euro_beech"];
    340343let groveActors = [
    341344    "actor|geology/highland1_moss.xml", "actor|geology/highland2_moss.xml",
    342345    "actor|props/flora/bush.xml", "actor|props/flora/bush_dry_a.xml", "actor|props/flora/bush_highlands.xml",
     
    383386    }
    384387}
    385388
    386 let foodEntities = ["gaia/flora_bush_berry", "gaia/fauna_chicken", "gaia/fauna_chicken"];
    387 // Start loaction resources
    388 function placeStartLocationResources(point)
     389
     390function placeStartLocationResources(point, foodEntities = ["gaia/flora_bush_berry", "gaia/fauna_chicken", "gaia/fauna_chicken"])
    389391{
    390392    let currentAngle = randFloat(0, TWO_PI);
    391393    // Stone and chicken
     
    438440    }
    439441}
    440442
     443log("Functions loaded after " + ((new Date().getTime() - genStartTime) / 1000) + "s"); // Time Check
     444
    441445/**
    442  * Set height limits and water level by map size
     446 * Environment settings
    443447 */
     448setBiome(g_BiomeAlpine);
     449g_Environment.Fog.FogColor = { "r": 0.8, "g": 0.8, "b": 0.8, "a": 0.01 };
     450g_Environment.Water.WaterBody.Colour = { "r" : 0.3, "g" : 0.05, "b" : 0.1, "a" : 0.1 };
     451g_Environment.Water.WaterBody.Murkiness = 0.4;
     452
     453/**
     454 * Base terrain shape generation and settings
     455 */
     456 // Height range by map size
    444457let heightScale = (g_Map.size + 256) / 768 / 4;
    445458let heightRange = { "min": MIN_HEIGHT * heightScale, "max": MAX_HEIGHT * heightScale };
    446 
     459// Water coverage
    447460let averageWaterCoverage = 1/5; // NOTE: Since terrain generation is quite unpredictable actual water coverage might vary much with the same value
    448461let waterHeight = -MIN_HEIGHT + heightRange.min + averageWaterCoverage * (heightRange.max - heightRange.min); // Water height in environment and the engine
    449462let waterHeightAdjusted = waterHeight + MIN_HEIGHT; // Water height in RMGEN
    450463setWaterHeight(waterHeight);
    451 
    452 
    453 /**
    454  * Generate base terrain
    455  */
     464// Generate base terrain shape
    456465let medH = (heightRange.min + heightRange.max) / 2;
    457466let initialHeightmap = [[medH, medH], [medH, medH]];
    458467setBaseTerrainDiamondSquare(heightRange.min, heightRange.max, initialHeightmap, 0.8);
    459 
    460 /**
    461  * Apply simple erosion
    462  */
    463 // globalSmoothHeightmap(0.5);
     468// Apply simple erosion
    464469for (let i = 0; i < 5; ++i)
    465470    splashErodeMap(0.1);
    466 
     471// Final rescale
    467472rescaleHeightmap(heightRange.min, heightRange.max);
    468473
     474RMS.SetProgress(25);
     475
    469476/**
    470  * Height presets
     477 * Prepare terrain texture placement
    471478 */
    472479let heighLimits = [
    473480    heightRange.min + 1/3 * (waterHeightAdjusted - heightRange.min), // 0 Deep water
     
    481488    waterHeightAdjusted + 6/8 * (heightRange.max - waterHeightAdjusted), // 8 Forest
    482489    waterHeightAdjusted + 7/8 * (heightRange.max - waterHeightAdjusted), // 9 Upper forest border
    483490    waterHeightAdjusted + (heightRange.max - waterHeightAdjusted)]; // 10 Hilltop
    484 
    485 /**
    486  * Set environment
    487  */
    488 setBiome(g_BiomeAlpine);
    489 g_Environment.Fog.FogColor = { "r": 0.8, "g": 0.8, "b": 0.8, "a": 0.01 };
    490 g_Environment.Water.WaterBody.Colour = { "r" : 0.3, "g" : 0.05, "b" : 0.1, "a" : 0.1 };
    491 g_Environment.Water.WaterBody.Murkiness = 0.4;
    492 
    493 /**
    494  * Add tile painting presets
    495  */
    496 let dummyActor = "actor|props/special/common/waypoint_flag.xml";
     491let playerHeight = (heighLimits[4] + heighLimits[5]) / 2; // Average player height
     492// Texture and actor presets
    497493let myBiome = [];
    498494myBiome.push({ // 0 Deep water
    499495    "texture": ["shoreline_stoney_a"],
     
    551547    "textureHS": ["alpine_cliff_c"], "actorHS": [["actor|geology/highland1.xml"], 0.0]
    552548});
    553549
     550log("Terrain shape generation and texture presets after " + ((new Date().getTime() - genStartTime) / 1000) + "s"); // Time Check
    554551
    555552/**
    556553 * Get start locations
     
    573570        teams.push(t);
    574571}
    575572playerIDs = sortPlayers(playerIDs);
    576 
    577573// Minimize maximum distance between players within a team
    578574if (teams.length)
    579575{
     
    616612    }
    617613}
    618614
    619 let playerHeight = (heighLimits[4] + heighLimits[5]) / 2;
     615log("Start location chosen after " + ((new Date().getTime() - genStartTime) / 1000) + "s"); // Time Check
     616RMS.SetProgress(30);
    620617
    621618/**
    622  * Place start locations (resources later)
     619 * Add paths
    623620 */
    624 for (let p = 0; p < playerIDs.length; ++p)
    625 {
    626     let point = startLocations[p];
    627     rectangularSmoothToHeight(point, 35, 35, playerHeight, 0.7);
    628     placeCivDefaultEntities(point.x, point.y, playerIDs[p], { "iberWall": true });
    629 }
    630 
    631 /**
    632  * Calculate tileCenteredHeightMap (This has nothing to to with TILE_CENTERED_HEIGHT_MAP which should be false (default) for this map to work properly)
    633  */
    634 let tchm = getTileCenteredHeightmap();
    635 
    636 /**
    637  * Add paths class and area but don't paint before resource spots are chosen!
    638  */
    639 let pathTerrainClassIDs = [];
     621let tchm = getTileCenteredHeightmap(); // Calculate tileCenteredHeightMap (This has nothing to to with TILE_CENTERED_HEIGHT_MAP which should be false)
     622let pathPoints = [];
     623let clPath = createTileClass();
    640624for (let i = 0; i < startLocations.length; ++i)
    641625{
    642626    let start = startLocations[i];
    643627    let target = startLocations[(i + 1) % startLocations.length];
    644     pathTerrainClassIDs.push(placeRandomPathToHeight(start, ["road_rome_a"], target, playerHeight, 8, 3, 0.1));
     628    pathPoints = pathPoints.concat(placeRandomPathToHeight(start, target, playerHeight, clPath));
    645629}
    646 let pathArea = [];
    647 for (let x = 0; x < tchm.length; ++x)
    648     for (let y = 0; y < tchm[0].length; ++y)
    649         for (let i = 0; i < pathTerrainClassIDs.length; ++i)
    650             if (getTileClass(pathTerrainClassIDs[i]).countMembersInRadius(x, y, 0.5))
    651                 pathArea.push({ "x": x, "y": y });
    652630
     631log("Paths placed after " + ((new Date().getTime() - genStartTime) / 1000) + "s"); // Time Check
     632RMS.SetProgress(45);
     633
    653634/**
    654  * Get resource spots after players start locations after path are calculated but before they are placed!
     635 * Get resource spots after players start locations calculation
    655636 */
    656637let avoidPoints = deepcopy(startLocations);
    657638for (let i = 0; i < avoidPoints.length; ++i)
    658639    avoidPoints[i].dist = 30;
    659 let resourceSpots = getPointsByHeight({ "min": (heighLimits[3] + heighLimits[4]) / 2, "max": (heighLimits[5] + heighLimits[6]) / 2 }, avoidPoints, pathArea);
     640let resourceSpots = getPointsByHeight({ "min": (heighLimits[3] + heighLimits[4]) / 2, "max": (heighLimits[5] + heighLimits[6]) / 2 }, avoidPoints, clPath);
    660641
    661 /**
    662  * Calculate slope map
    663  */
    664 let slopeMap = getSlopeMap();
     642log("Resource spots chosen after " + ((new Date().getTime() - genStartTime) / 1000) + "s"); // Time Check
     643RMS.SetProgress(55);
    665644
    666645/**
    667646 * Divide tiles in areas by height and avoid paths
     
    673652{
    674653    for (let y = 0; y < tchm[0].length; ++y)
    675654    {
    676         let isPath = false;
    677         for (let i = 0; i < pathArea.length; ++i)
    678             if (pathArea[i].x == x && pathArea[i].y == y)
    679                 isPath = true;
    680         if (isPath)
     655        if (g_Map.tileClasses[clPath].inclusionCount[x][y] > 0) // Avoid paths
    681656            continue;
    682657       
    683658        let minHeight = heightRange.min;
     
    697672/**
    698673 * Get max slope of each area
    699674 */
     675let slopeMap = getSlopeMap(); // Calculate slope map
    700676let minSlope = [];
    701677let maxSlope = [];
    702678for (let h = 0; h < heighLimits.length; ++h)
     
    744720    }
    745721}
    746722
     723log("Terrain texture placement finished after " + ((new Date().getTime() - genStartTime) / 1000) + "s"); // Time Check
     724RMS.SetProgress(80);
     725
    747726/**
    748  * Add starting resources after terrain texture painting
     727 * Add start locations and resource spots after terrain texture and path painting
    749728 */
    750 for (let p = 0; p < g_MapSettings.PlayerData.length - 1; ++p)
     729for (let p = 0; p < playerIDs.length; ++p)
     730{
     731    let point = startLocations[p];
     732    rectangularSmoothToHeight(point, 40, 40, playerHeight, 0.7);
     733    placeCivDefaultEntities(point.x, point.y, playerIDs[p], { "iberWall": true });
    751734    placeStartLocationResources(startLocations[p]);
    752 
    753 /**
    754  * Add resource spots after terrain texture painting
    755  */
     735}
    756736for (let i = 0; i < resourceSpots.length; ++i)
    757737{
    758738    let choice = i % 5;
     
    771751/**
    772752 * Stop Timer
    773753 */
    774 log("Map generation finished after " + ((new Date().getTime() - genStartTime) / 1000) + "s")
     754log("Map generation finished after " + ((new Date().getTime() - genStartTime) / 1000) + "s");
    775755
    776756/**
    777757 * Export map data