Index: binaries/data/mods/public/maps/random/BaseTerrainDiamondSquare.js
===================================================================
--- binaries/data/mods/public/maps/random/BaseTerrainDiamondSquare.js	(revision 0)
+++ binaries/data/mods/public/maps/random/BaseTerrainDiamondSquare.js	(working copy)
@@ -0,0 +1,146 @@
+/**
+*	ToDo:
+*	Add resources at start locations
+*	Add stone and metal
+*	Place start locations of one team close to each other
+*
+*	Add parameters for match setup screen (for later use and demonstration)
+*
+*	Extract some functions to an RMGEN lib
+*	Sort out unneeded functions calling other functions
+*	Clean up
+*/
+
+RMS.LoadLibrary("rmgen");
+
+const BUILDING_ANGlE = -PI/4;
+
+/**
+* initialize map
+*/
+
+log("Initializing map...");
+
+InitMap();
+
+var numPlayers = g_MapSettings.PlayerData.length;
+var mapSize = getMapSize();
+
+
+/**
+* Actually do stuff
+*/
+
+/**
+* Set target min and max height depending on map size to make average steepness about the same on all map sizes
+*/
+var heightRange = {"min": MIN_HEIGHT * (mapSize + 512) / 1024 / 8, "max": MAX_HEIGHT * (mapSize + 512) / 1024 / 8};
+
+/**
+* Set average water coverage
+*/
+var averageWaterCoverage = 1/5; // NOTE: Since erosion is not predictable actual water coverage might vary much with the same values
+var waterHeight = -MIN_HEIGHT + heightRange.min + averageWaterCoverage * (heightRange.max - heightRange.min);
+var waterHeightAdjusted = waterHeight + MIN_HEIGHT;
+setWaterHeight(waterHeight);
+
+/**
+*  Generate initial reliefmap
+*/
+setBaseTerrainDiamondSquare(heightRange.min, heightRange.max, 0.5);
+
+
+/**
+* Apply simple erosion
+*/
+for (var i = 0; i < 5; i++)
+	globalSmoothHeightmap(0.5);
+
+
+/**
+* Place start locations and apply terrain texture and decorative props by height
+*/
+
+/**
+* Set random biome
+*/
+randomizeBiome();
+
+/**
+* Define texture textures and decorative props (and density) by height
+*/
+var textueByHeight = [];
+textueByHeight.push({"height": heightRange.min + 1/3 * (waterHeightAdjusted - heightRange.min), "texture": rbt15, "actor": [rbe9, 0.2]});
+textueByHeight.push({"height": heightRange.min + 2/3 * (waterHeightAdjusted - heightRange.min), "texture": rbt15, "actor": [undefined, 0]});
+textueByHeight.push({"height": heightRange.min + 3/3 * (waterHeightAdjusted - heightRange.min), "texture": rbt15, "actor": [rba3, 0.2]});
+textueByHeight.push({"height": waterHeightAdjusted + 1/9 * (heightRange.max - waterHeightAdjusted), "texture": rbt14, "actor": [rbe5, 0.1]});
+textueByHeight.push({"height": waterHeightAdjusted + 2/9 * (heightRange.max - waterHeightAdjusted), "texture": rbt8, "actor": [undefined, 0]});
+textueByHeight.push({"height": waterHeightAdjusted + 3/9 * (heightRange.max - waterHeightAdjusted), "texture": rbt9, "actor": [undefined, 0]});
+textueByHeight.push({"height": waterHeightAdjusted + 4/9 * (heightRange.max - waterHeightAdjusted), "texture": rbt1, "actor": [undefined, 0]});
+textueByHeight.push({"height": waterHeightAdjusted + 5/9 * (heightRange.max - waterHeightAdjusted), "texture": rbt5, "actor": [rbe3, 0.2]});
+textueByHeight.push({"height": waterHeightAdjusted + 6/9 * (heightRange.max - waterHeightAdjusted), "texture": rbt2, "actor": [rbe1, 0.4]});
+textueByHeight.push({"height": waterHeightAdjusted + 7/9 * (heightRange.max - waterHeightAdjusted), "texture": rbt3, "actor": [rbe2, 0.4]});
+textueByHeight.push({"height": waterHeightAdjusted + 8/9 * (heightRange.max - waterHeightAdjusted), "texture": rbt7, "actor": [rbe4, 0.2]});
+textueByHeight.push({"height": waterHeightAdjusted + 9/9 * (heightRange.max - waterHeightAdjusted), "texture": rbt4, "actor": [undefined, 0]});
+
+/**
+* Get start locations
+*/
+rescaleHeightmap(heightRange.min, heightRange.max);
+var startLocations = getStartLocationsByHeightmap({"min": textueByHeight[4].height, "max": textueByHeight[5].height});
+
+/**
+* Smooth ground at start locations and place starting entities
+*/
+var playerHeight = (textueByHeight[4].height + textueByHeight[5].height) / 2;
+for (var p = 0; p < g_MapSettings.PlayerData.length - 1; p++)
+{
+	log("p = " + uneval(p));
+	log("startLocations[" + p + "] = " + uneval(startLocations[p]));
+	rectangularSmoothToHeight(startLocations[p], 30, 30, playerHeight);
+	placeCivDefaultEntities(startLocations[p].x, startLocations[p].y, p + 1, BUILDING_ANGlE, {"iberWall": true});
+}
+
+/**
+* Normalize and apply reliefmap
+*/
+rescaleHeightmap(heightRange.min, heightRange.max);
+
+/**
+* Place terrain texture and decorative props by height
+*/
+for(var x = 0; x < mapSize; x++)
+{
+	for (var y = 0; y < mapSize; y++)
+	{
+		var textureMinHeight = heightRange.min;
+		for (var i = 0; i < textueByHeight.length; i++)
+		{
+			if (g_Map.height[x][y] >= textureMinHeight && g_Map.height[x][y] <= textueByHeight[i].height)
+			{
+				if (typeof(textueByHeight[i].texture) == "string")
+					g_Map.setTexture(x, y, textueByHeight[i].texture);
+				else
+					g_Map.setTexture(x, y, textueByHeight[i].texture[randInt(textueByHeight[i].texture.length)]);
+				if (textueByHeight[i].actor[0])
+				{
+					var scaleByDistToPlayer = 1; // ToDo: Make an approximate faster range check!!!
+					for (var p = 0; p < g_MapSettings.PlayerData.length; p++)
+						scaleByDistToPlayer = min(getDistance(x, y, startLocations[p].x, startLocations[p].y) / 50, scaleByDistToPlayer);
+					if (randFloat() < textueByHeight[i].actor[1] * scaleByDistToPlayer)
+						placeObject(x + 0.5, y + 0.5, textueByHeight[i].actor[0], 0, randFloat(0, 2*PI));
+				}
+				break;
+			}
+			else
+			{
+				textureMinHeight = textueByHeight[i].height;
+			}
+		}
+	}
+}
+
+/**
+* Export map data
+*/
+ExportMap();
Index: binaries/data/mods/public/maps/random/BaseTerrainDiamondSquare.json
===================================================================
--- binaries/data/mods/public/maps/random/BaseTerrainDiamondSquare.json	(revision 0)
+++ binaries/data/mods/public/maps/random/BaseTerrainDiamondSquare.json	(working copy)
@@ -0,0 +1,12 @@
+{
+	"settings" : {
+		"Name" : "Base Terrain Diamond Square Test",
+		"Script" : "BaseTerrainDiamondSquare.js",
+		"Description" : "Testmap for the diamond-square base terrain generation.",
+		"CircularMap" : false,
+		"BaseTerrain" : "grass1_spring",
+		"BaseHeight" : 0,
+		"Keywords": ["demo"],
+		"XXXXXX" : "Optionally define other things here, like we would for a scenario"
+	}
+}
\ No newline at end of file
Index: binaries/data/mods/public/maps/random/belgian_uplands.js
===================================================================
--- binaries/data/mods/public/maps/random/belgian_uplands.js	(revision 17723)
+++ binaries/data/mods/public/maps/random/belgian_uplands.js	(working copy)
@@ -1,14 +1,19 @@
-// Prepare progress calculation
+/**
+ * Prepare progress calculation
+ */
 var timeArray = [];
 timeArray.push(new Date().getTime());
 
-// Importing rmgen libraries
+/**
+ * Importing rmgen libraries
+ */
 RMS.LoadLibrary("rmgen");
 
 const BUILDING_ANGlE = -PI/4;
 
-// initialize map
-
+/**
+ * initialize map
+ */
 log("Initializing map...");
 
 InitMap();
@@ -17,15 +22,13 @@
 var mapSize = getMapSize();
 
 
-//////////
-// Heightmap functionality
-//////////
+/**
+ * Heightmap functionality
+ */
 
-// Some general heightmap settings
-const MIN_HEIGHT = - SEA_LEVEL; // 20, should be set in the libs!
-const MAX_HEIGHT = 0xFFFF/HEIGHT_UNITS_PER_METRE - SEA_LEVEL; // A bit smaler than 90, should be set in the libs!
-
-// Add random heightmap generation functionality
+/**
+ * Add random heightmap generation functionality
+ */
 function getRandomReliefmap(minHeight, maxHeight)
 {
 	minHeight = (minHeight || MIN_HEIGHT);
@@ -35,10 +38,10 @@
 	if (maxHeight > MAX_HEIGHT)
 		warn("getRandomReliefmap: Argument maxHeight is smaler then the supported maximum height of " + MAX_HEIGHT + " (const MAX_HEIGHT): " + maxHeight)
 	var reliefmap = [];
-	for (var x = 0; x <= mapSize; x++)
+	for (var x = 0; x <= mapSize; ++x)
 	{
 		reliefmap.push([]);
-		for (var y = 0; y <= mapSize; y++)
+		for (var y = 0; y <= mapSize; ++y)
 		{
 			reliefmap[x].push(randFloat(minHeight, maxHeight));
 		}
@@ -46,28 +49,32 @@
 	return reliefmap;
 }
 
-// Apply a heightmap
+/**
+ * Apply a heightmap
+ */
 function setReliefmap(reliefmap)
 {
 	// g_Map.height = reliefmap;
-	for (var x = 0; x <= mapSize; x++)
+	for (var x = 0; x <= mapSize; ++x)
 	{
-		for (var y = 0; y <= mapSize; y++)
+		for (var y = 0; y <= mapSize; ++y)
 		{
 			setHeight(x, y, reliefmap[x][y]);
 		}
 	}
 }
 
-// Get minimum and maxumum height used in a heightmap
+/**
+ * Get minimum and maxumum height used in a heightmap
+ */
 function getMinAndMaxHeight(reliefmap)
 {
 	var height = {};
 	height.min = Infinity;
 	height.max = -Infinity;
-	for (var x = 0; x <= mapSize; x++)
+	for (var x = 0; x <= mapSize; ++x)
 	{
-		for (var y = 0; y <= mapSize; y++)
+		for (var y = 0; y <= mapSize; ++y)
 		{
 			if (reliefmap[x][y] < height.min)
 				height.min = reliefmap[x][y];
@@ -78,7 +85,9 @@
 	return height;
 }
 
-// Rescale a heightmap (Waterlevel is not taken into consideration!)
+/**
+ * Rescale a heightmap (Waterlevel is not taken into consideration!)
+ */
 function getRescaledReliefmap(reliefmap, minHeight, maxHeight)
 {
 	var newReliefmap = deepcopy(reliefmap);
@@ -89,9 +98,9 @@
 	if (maxHeight > MAX_HEIGHT)
 		warn("getRescaledReliefmap: Argument maxHeight is smaler then the supported maximum height of " + MAX_HEIGHT + " (const MAX_HEIGHT): " + maxHeight)
 	var oldHeightRange = getMinAndMaxHeight(reliefmap);
-	for (var x = 0; x <= mapSize; x++)
+	for (var x = 0; x <= mapSize; ++x)
 	{
-		for (var y = 0; y <= mapSize; y++)
+		for (var y = 0; y <= mapSize; ++y)
 		{
 			newReliefmap[x][y] = minHeight + (reliefmap[x][y] - oldHeightRange.min) / (oldHeightRange.max - oldHeightRange.min) * (maxHeight - minHeight);
 		}
@@ -99,18 +108,20 @@
 	return newReliefmap
 }
 
-// Applying decay errosion (terrain independent)
+/**
+ * Applying decay errosion (terrain independent)
+ */
 function getHeightErrosionedReliefmap(reliefmap, strength)
 {
 	var newReliefmap = deepcopy(reliefmap);
 	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
 	var map = [[1, 0], [1, 1], [0, 1], [-1, 1], [-1, 0], [-1, -1], [0, -1], [1, -1]]; // Default
-	for (var x = 0; x <= mapSize; x++)
+	for (var x = 0; x <= mapSize; ++x)
 	{
-		for (var y = 0; y <= mapSize; y++)
+		for (var y = 0; y <= mapSize; ++y)
 		{
 			var div = 0;
-			for (var i = 0; i < map.length; i++)
+			for (var i = 0; i < map.length; ++i)
 				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
 		}
 	}
@@ -118,14 +129,18 @@
 }
 
 
-//////////
-// Prepare for hightmap munipulation
-//////////
+/**
+ * Prepare for hightmap munipulation
+ */
 
-// Set target min and max height depending on map size to make average stepness the same on all map sizes
-var heightRange = {"min": MIN_HEIGHT * mapSize / 8192, "max": MAX_HEIGHT * mapSize / 8192};
+/**
+ * Set target min and max height depending on map size to make average stepness the same on all map sizes
+ */
+var heightRange = { "min": MIN_HEIGHT * (mapSize + 256) / 8192, "max": MAX_HEIGHT * (mapSize + 256) / 8192 };
 
-// Set average water coverage
+/**
+ * Set average water coverage
+ */
 var averageWaterCoverage = 1/3; // NOTE: Since errosion is not predictable actual water coverage might differ much with the same value
 if (mapSize < 200) // Sink the waterlevel on tiny maps to ensure enough space
 	averageWaterCoverage = 2/3 * averageWaterCoverage;
@@ -134,77 +149,104 @@
 setWaterHeight(waterHeight);
 
 
-//////////
-// Prepare terrain texture by height placement
-//////////
-
+/**
+ * Prepare terrain texture by height placement
+ */
 var textueByHeight = [];
 
-// Deep water
-textueByHeight.push({"upperHeightLimit": heightRange.min + 1/3 * (waterHeightAdjusted - heightRange.min), "terrain": "temp_sea_rocks"});
-// Medium deep water (with fish)
-var terreins = ["temp_sea_weed"];
-terreins = terreins.concat(terreins, terreins, terreins, terreins);
-terreins = terreins.concat(terreins, terreins, terreins, terreins);
-terreins.push("temp_sea_weed|gaia/fauna_fish");
-textueByHeight.push({"upperHeightLimit": heightRange.min + 2/3 * (waterHeightAdjusted - heightRange.min), "terrain": terreins});
-// Flat Water
-textueByHeight.push({"upperHeightLimit": heightRange.min + 3/3 * (waterHeightAdjusted - heightRange.min), "terrain": "temp_mud_a"});
-// Water surroundings/bog (with stone/metal some rabits and bushes)
-var terreins = ["temp_plants_bog", "temp_plants_bog_aut", "temp_dirt_gravel_plants", "temp_grass_d"];
-terreins = terreins.concat(terreins, terreins, terreins, terreins, terreins);
-terreins = ["temp_plants_bog|gaia/flora_bush_temperate"].concat(terreins, terreins);
-terreins = ["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);
-terreins = ["temp_plants_bog_aut|gaia/flora_tree_dead"].concat(terreins, terreins);
-textueByHeight.push({"upperHeightLimit": waterHeightAdjusted + 1/6 * (heightRange.max - waterHeightAdjusted), "terrain": terreins});
-// Juicy grass near bog
-textueByHeight.push({"upperHeightLimit": waterHeightAdjusted + 2/6 * (heightRange.max - waterHeightAdjusted),
-	"terrain": ["temp_grass", "temp_grass_d", "temp_grass_long_b", "temp_grass_plants"]});
-// Medium level grass
-// var testActor = "actor|geology/decal_stone_medit_a.xml";
-textueByHeight.push({"upperHeightLimit": waterHeightAdjusted + 3/6 * (heightRange.max - waterHeightAdjusted),
-	"terrain": ["temp_grass", "temp_grass_b", "temp_grass_c", "temp_grass_mossy"]});
-// Long grass near forest border
-textueByHeight.push({"upperHeightLimit": waterHeightAdjusted + 4/6 * (heightRange.max - waterHeightAdjusted),
-	"terrain": ["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"]});
-// Forest border (With wood/food plants/deer/rabits)
-var terreins = ["temp_grass_plants|gaia/flora_tree_euro_beech", "temp_grass_mossy|gaia/flora_tree_poplar", "temp_grass_mossy|gaia/flora_tree_poplar_lombardy",
+/**
+ * Deep water
+ */
+textueByHeight.push({ "upperHeightLimit": heightRange.min + 1/3 * (waterHeightAdjusted - heightRange.min), "terrain": "temp_sea_rocks" });
+
+/**
+ * Medium water (with fish)
+ */
+var terrains = ["temp_sea_weed"];
+terrains = terrains.concat(terrains, terrains, terrains, terrains);
+terrains = terrains.concat(terrains, terrains, terrains, terrains);
+terrains.push("temp_sea_weed|gaia/fauna_fish");
+textueByHeight.push({ "upperHeightLimit": heightRange.min + 2/3 * (waterHeightAdjusted - heightRange.min), "terrain": terrains });
+
+/**
+ * Flat Water
+ */
+textueByHeight.push({ "upperHeightLimit": heightRange.min + 3/3 * (waterHeightAdjusted - heightRange.min), "terrain": "temp_mud_a" });
+
+/**
+ * Water surroundings/bog (with stone/metal some rabits and bushes)
+ */
+var terrains = ["temp_plants_bog", "temp_plants_bog_aut", "temp_dirt_gravel_plants", "temp_grass_d"];
+terrains = terrains.concat(terrains, terrains, terrains, terrains, terrains);
+terrains = ["temp_plants_bog|gaia/flora_bush_temperate"].concat(terrains, terrains);
+terrains = ["temp_dirt_gravel_plants|gaia/geology_metal_temperate", "temp_dirt_gravel_plants|gaia/geology_stone_temperate", "temp_plants_bog|gaia/fauna_rabbit"].concat(terrains, terrains);
+terrains = ["temp_plants_bog_aut|gaia/flora_tree_dead"].concat(terrains, terrains);
+textueByHeight.push({ "upperHeightLimit": waterHeightAdjusted + 1/6 * (heightRange.max - waterHeightAdjusted), "terrain": terrains });
+
+/**
+ * Juicy grass near bog
+ */
+textueByHeight.push({ "upperHeightLimit": waterHeightAdjusted + 2/6 * (heightRange.max - waterHeightAdjusted),
+	"terrain": ["temp_grass", "temp_grass_d", "temp_grass_long_b", "temp_grass_plants"] });
+
+/**
+ * Medium level grass
+ */
+textueByHeight.push({ "upperHeightLimit": waterHeightAdjusted + 3/6 * (heightRange.max - waterHeightAdjusted),
+	"terrain": ["temp_grass", "temp_grass_b", "temp_grass_c", "temp_grass_mossy"] });
+
+/**
+ * Long grass near forest border
+ */
+textueByHeight.push({ "upperHeightLimit": waterHeightAdjusted + 4/6 * (heightRange.max - waterHeightAdjusted),
+	"terrain": ["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"] });
+
+/**
+ * Forest border (With wood/food plants/deer/rabits)
+ */
+var terrains = ["temp_grass_plants|gaia/flora_tree_euro_beech", "temp_grass_mossy|gaia/flora_tree_poplar", "temp_grass_mossy|gaia/flora_tree_poplar_lombardy",
 	"temp_grass_long|gaia/flora_bush_temperate", "temp_mud_plants|gaia/flora_bush_temperate", "temp_mud_plants|gaia/flora_bush_badlands",
 	"temp_grass_long|gaia/flora_tree_apple", "temp_grass_clovers|gaia/flora_bush_berry", "temp_grass_clovers_2|gaia/flora_bush_grapes",
 	"temp_grass_plants|gaia/fauna_deer", "temp_grass_long_b|gaia/fauna_rabbit"];
-var numTerreins = terreins.length;
-for (var i = 0; i < numTerreins; i++)
-	terreins.push("temp_grass_plants");
-textueByHeight.push({"upperHeightLimit": waterHeightAdjusted + 5/6 * (heightRange.max - waterHeightAdjusted), "terrain": terreins});
-// Unpassable woods
-textueByHeight.push({"upperHeightLimit": waterHeightAdjusted + 6/6 * (heightRange.max - waterHeightAdjusted),
+var numTerreins = terrains.length;
+for (var i = 0; i < numTerreins; ++i)
+	terrains.push("temp_grass_plants");
+textueByHeight.push({ "upperHeightLimit": waterHeightAdjusted + 5/6 * (heightRange.max - waterHeightAdjusted), "terrain": terrains });
+
+/**
+ * Impassable woods
+ */
+textueByHeight.push({ "upperHeightLimit": waterHeightAdjusted + 6/6 * (heightRange.max - waterHeightAdjusted),
 	"terrain": ["temp_grass_mossy|gaia/flora_tree_oak", "temp_forestfloor_pine|gaia/flora_tree_pine",
 	"temp_grass_mossy|gaia/flora_tree_oak", "temp_forestfloor_pine|gaia/flora_tree_pine",
 	"temp_mud_plants|gaia/flora_tree_dead", "temp_plants_bog|gaia/flora_tree_oak_large",
-	"temp_dirt_gravel_plants|gaia/flora_tree_aleppo_pine", "temp_forestfloor_autumn|gaia/flora_tree_carob"]});
+	"temp_dirt_gravel_plants|gaia/flora_tree_aleppo_pine", "temp_forestfloor_autumn|gaia/flora_tree_carob"] });
 var minTerrainDistToBorder = 3;
 
-// Time check 1
+/**
+ * Time check 1
+ */
 timeArray.push(new Date().getTime());
 RMS.SetProgress(5);
 
-
-// START THE GIANT WHILE LOOP:
-// - Generate Heightmap
-// - Search valid start position tiles
-// - Choose a good start position derivation (largest distance between closest players)
-// - Restart the loop if start positions are invalid or two players are to close to each other
+/**
+ * START THE GIANT WHILE LOOP:
+ * - Generate Heightmap
+ * - Search valid start position tiles
+ * - Choose a good start position derivation (largest distance between closest players)
+ * - Restart the loop if start positions are invalid or two players are to close to each other
+ */
 var goodStartPositionsFound = false;
 var minDistBetweenPlayers = 16 + mapSize / 16; // Don't set this higher than 25 for tiny maps! It will take forever with 8 players!
 var enoughTiles = false;
 var tries = 0;
 while (!goodStartPositionsFound)
 {
-	tries++;
+	++tries;
 	log("Starting giant while loop try " + tries);
 	// Generate reliefmap
 	var myReliefmap = getRandomReliefmap(heightRange.min, heightRange.max);
-	for (var i = 0; i < 50 + mapSize/4; i++) // Cycles depend on mapsize (more cycles -> bigger structures)
+	for (var i = 0; i < 50 + mapSize/4; ++i) // Cycles depend on mapsize (more cycles -> bigger structures)
 		myReliefmap = getHeightErrosionedReliefmap(myReliefmap, 1);
 	myReliefmap = getRescaledReliefmap(myReliefmap, heightRange.min, heightRange.max);
 	setReliefmap(myReliefmap);
@@ -217,18 +259,18 @@
 	var lowerHeightLimit = textueByHeight[3].upperHeightLimit;
 	var upperHeightLimit = textueByHeight[6].upperHeightLimit;
 	// Check for valid points by height
-	for (var x = distToBorder + minTerrainDistToBorder; x < mapSize - distToBorder - minTerrainDistToBorder; x++)
+	for (var x = distToBorder + minTerrainDistToBorder; x < mapSize - distToBorder - minTerrainDistToBorder; ++x)
 	{
-		for (var y = distToBorder + minTerrainDistToBorder; y < mapSize - distToBorder - minTerrainDistToBorder; y++)
+		for (var y = distToBorder + minTerrainDistToBorder; y < mapSize - distToBorder - minTerrainDistToBorder; ++y)
 		{
 			var actualHeight = getHeight(x, y);
 			if (actualHeight > lowerHeightLimit && actualHeight < upperHeightLimit)
 			{
 				// Check for points within a valid area by height (rectangular since faster)
 				var isPossible = true;
-				for (var offX = - neededDistance; offX <= neededDistance; offX++)
+				for (var offX = - neededDistance; offX <= neededDistance; ++offX)
 				{
-					for (var offY = - neededDistance; offY <= neededDistance; offY++)
+					for (var offY = - neededDistance; offY <= neededDistance; ++offY)
 					{
 						var testHeight = getHeight(x + offX, y + offY);
 						if (testHeight <= lowerHeightLimit || testHeight >= upperHeightLimit)
@@ -252,7 +294,7 @@
 	// Reduce to tiles in a circle of mapSize / 2 distance to the center (to avoid players placed in corners)
 	var possibleStartPositionsTemp = [];
 	var maxDistToCenter = mapSize / 2;
-	for (var i = 0; i < possibleStartPositions.length; i++)
+	for (var i = 0; i < possibleStartPositions.length; ++i)
 	{
 		var deltaX = possibleStartPositions[i][0] - mapSize / 2;
 		var deltaY = possibleStartPositions[i][1] - mapSize / 2;
@@ -270,19 +312,19 @@
 	var maxDistToResources = distToBorder; // Has to be <= distToBorder!
 	var minNumLowTiles = 10;
 	var minNumHighTiles = 10;
-	for (var i = 0; i < possibleStartPositions.length; i++)
+	for (var i = 0; i < possibleStartPositions.length; ++i)
 	{
 		var numLowTiles = 0;
 		var numHighTiles = 0;
-		for (var dx = - maxDistToResources; dx < maxDistToResources; dx++)
+		for (var dx = - maxDistToResources; dx < maxDistToResources; ++dx)
 		{
-			for (var dy = - maxDistToResources; dy < maxDistToResources; dy++)
+			for (var dy = - maxDistToResources; dy < maxDistToResources; ++dy)
 			{
 				var testHeight = getHeight(possibleStartPositions[i][0] + dx, possibleStartPositions[i][1] + dy);
 				if (testHeight < lowerHeightLimit)
-					numLowTiles++;
+					++numLowTiles;
 				if (testHeight > upperHeightLimit)
-					numHighTiles++;
+					++numHighTiles;
 				if (numLowTiles > minNumLowTiles && numHighTiles > minNumHighTiles)
 					break;
 			}
@@ -311,22 +353,22 @@
 		// Get some random start location derivations. NOTE: Itterating over all possible derivations is just to much (valid points ** numPlayers)
 		var maxTries = 100000; // floor(800000 / (Math.pow(numPlayers, 2) / 2));
 		var possibleDerivations = [];
-		for (var i = 0; i < maxTries; i++)
+		for (var i = 0; i < maxTries; ++i)
 		{
 			var vector = [];
-			for (var p = 0; p < numPlayers; p++)
+			for (var p = 0; p < numPlayers; ++p)
 				vector.push(randInt(possibleStartPositions.length));
 			possibleDerivations.push(vector);
 		}
 		
 		// Choose the start location derivation with the greatest minimum distance between players
 		var maxMinDist = 0;
-		for (var d = 0; d < possibleDerivations.length; d++)
+		for (var d = 0; d < possibleDerivations.length; ++d)
 		{
 			var minDist = 2 * mapSize;
-			for (var p1 = 0; p1 < numPlayers - 1; p1++)
+			for (var p1 = 0; p1 < numPlayers - 1; ++p1)
 			{
-				for (var p2 = p1 + 1; p2 < numPlayers; p2++)
+				for (var p2 = p1 + 1; p2 < numPlayers; ++p2)
 				{
 					if (p1 != p2)
 					{
@@ -358,26 +400,28 @@
 	} // End of derivation check
 } // END THE GIANT WHILE LOOP
 
-// Time check 2
+/**
+ * Time check 2
+ */
 timeArray.push(new Date().getTime());
 RMS.SetProgress(60);
 
 
-////////
-// Paint terrain by height and add props
-////////
+/**
+ * Paint terrain by height and add props
+ */
 
 var propDensity = 1; // 1 means as determined in the loop, less for large maps as set below
 if (mapSize > 500)
 	propDensity = 1/4;
 else if (mapSize > 400)
 	propDensity = 3/4;
-for(var x = minTerrainDistToBorder; x < mapSize - minTerrainDistToBorder; x++)
+for(var x = minTerrainDistToBorder; x < mapSize - minTerrainDistToBorder; ++x)
 {
-	for (var y = minTerrainDistToBorder; y < mapSize - minTerrainDistToBorder; y++)
+	for (var y = minTerrainDistToBorder; y < mapSize - minTerrainDistToBorder; ++y)
 	{
 		var textureMinHeight = heightRange.min;
-		for (var i = 0; i < textueByHeight.length; i++)
+		for (var i = 0; i < textueByHeight.length; ++i)
 		{
 			if (getHeight(x, y) >= textureMinHeight && getHeight(x, y) <= textueByHeight[i].upperHeightLimit)
 			{
@@ -488,20 +532,22 @@
 	}
 }
 
-// Time check 3
+/**
+ * Time check 3
+ */
 timeArray.push(new Date().getTime());
 RMS.SetProgress(90);
 
 
-////////
-// Place players and start resources
-////////
+/**
+ * Place players and start resources
+ */
 
-for (var p = 0; p < numPlayers; p++)
+for (var p = 0; p < numPlayers; ++p)
 {
 	var actualX = possibleStartPositions[bestDerivation[p]][0];
 	var actualY = possibleStartPositions[bestDerivation[p]][1];
-	placeCivDefaultEntities(actualX, actualY, p + 1, BUILDING_ANGlE, {"iberWall" : false});
+	placeCivDefaultEntities(actualX, actualY, p + 1, BUILDING_ANGlE, { "iberWall" : false });
 	// Place some start resources
 	var uDist = 8;
 	var uSpace = 1;
@@ -509,7 +555,7 @@
 	{
 		var uAngle = BUILDING_ANGlE - PI * (2-j) / 2;
 		var count = 4;
-		for (var numberofentities = 0; numberofentities < count; numberofentities++)
+		for (var numberofentities = 0; numberofentities < count; ++numberofentities)
 		{
 			var ux = actualX + uDist * cos(uAngle) + numberofentities * uSpace * cos(uAngle + PI/2) - (0.75 * uSpace * floor(count / 2) * cos(uAngle + PI/2));
 			var uz = actualY + uDist * sin(uAngle) + numberofentities * uSpace * sin(uAngle + PI/2) - (0.75 * uSpace * floor(count / 2) * sin(uAngle + PI/2));
@@ -521,17 +567,22 @@
 	}
 }
 
-
-// Export map data
+/**
+ * Export map data
+ */
 ExportMap();
 
-// Time check 7
+/**
+ * Time check 7
+ */
 timeArray.push(new Date().getTime());
 
-// Calculate progress percentage with the time checks
+/**
+ * Calculate progress percentage with the time checks
+ */
 var generationTime = timeArray[timeArray.length - 1] - timeArray[0];
 log("Total generation time (ms): " + generationTime);
-for (var i = 0; i < timeArray.length; i++)
+for (var i = 0; i < timeArray.length; ++i)
 {
 	var timeSinceStart = timeArray[i] - timeArray[0];
 	var progressPercentage = 100 * timeSinceStart / generationTime;
Index: binaries/data/mods/public/maps/random/realisticTerrainDemo.js
===================================================================
--- binaries/data/mods/public/maps/random/realisticTerrainDemo.js	(revision 0)
+++ binaries/data/mods/public/maps/random/realisticTerrainDemo.js	(working copy)
@@ -0,0 +1,522 @@
+/**
+*	ToDo:
+*	Add further biomes
+*	Place start locations of one team close to each other
+*	Raise the entire map if to much water
+*
+*	Add support for circular maps
+*	Add parameters for match setup screen (for later use and demonstration)
+*
+*	Extract some functions to an RMGEN lib
+*	Sort out unneeded functions calling other functions
+*	Clean up
+*/
+
+/**
+* DEBUG Start Timer
+*/
+var genStartTime = new Date().getTime();
+
+RMS.LoadLibrary("rmgen");
+
+const BUILDING_ANGlE = -PI/4;
+
+/**
+* initialize map
+*/
+log("Initializing map...");
+InitMap();
+
+
+/**
+*  Some general functions
+*/
+
+/**
+*	Takes an array of 2D points (arrays of length 2)
+*	Returns the order to go through the points for the shortest closed path (array of indices)
+*/
+function getOrderOfPointsForShortestClosePath(points)
+{
+	var order = [];
+	var distances = [];
+	if (points.length <= 3)
+	{
+		for (var i = 0; i < points.length; ++i)
+			order.push(i);
+		
+		return order;
+	}
+	
+	// Just add the first 3 points
+	var pointsToAdd = deepcopy(points);
+	for (var i = 0; i < min(points.length, 3); ++i)
+	{
+		order.push(i)
+		pointsToAdd.shift(i);
+		if (i)
+			distances.push(getDistance(points[order[i]].x, points[order[i]].y, points[order[i - 1]].x, points[order[i - 1]].y));
+	}
+	distances.push(getDistance(points[order[0]].x, points[order[0]].y, points[order[order.length - 1]].x, points[order[order.length - 1]].y))
+	
+	// Add remaining points so the path lengthens the least
+	var numPointsToAdd = pointsToAdd.length;
+	for (var i = 0; i < numPointsToAdd; ++i)
+	{
+		var indexToAddTo = undefined;
+		var minEnlengthen = Infinity;
+		var minDist1 = 0;
+		var minDist2 = 0;
+		for (var k = 0; k < order.length; ++k)
+		{
+			var dist1 = getDistance(pointsToAdd[0].x, pointsToAdd[0].y, points[order[k]].x, points[order[k]].y);
+			var dist2 = getDistance(pointsToAdd[0].x, pointsToAdd[0].y, points[order[(k + 1) % order.length]].x, points[order[(k + 1) % order.length]].y);
+			var enlengthen = dist1 + dist2 - distances[k];
+			if (enlengthen < minEnlengthen)
+			{
+				indexToAddTo = k;
+				minEnlengthen = enlengthen;
+				minDist1 = dist1;
+				minDist2 = dist2;
+			}
+		}
+		order.splice(indexToAddTo + 1, 0, i + 3);
+		distances.splice(indexToAddTo, 1, minDist1, minDist2);
+		pointsToAdd.shift();
+	}
+	
+	return order;
+}
+
+/*
+Drags a path to a target height smoothing it at the edges and return some points on the path.
+
+TODO:
+Would be nice to tell the function what to do and how often in the arguments
+Adding painted tiles to a tile class
+*/
+function placeRandomPathToHeight(start, paintPathWithTexture, target, targetHeight, width, occurrence, strength, heightmap)
+{
+	if (paintPathWithTexture === false)
+		paintPathWithTexture = [false, ""];
+	else if (paintPathWithTexture === true)
+		paintPathWithTexture = [true, ['temp_road', "temp_road_overgrown", 'temp_grass_b']]
+	else
+		paintPathWithTexture = (paintPathWithTexture || [false, ['temp_road', "temp_road_overgrown", 'temp_grass_b']]);
+	var paintPath = paintPathWithTexture[0];
+	var pathTexture = paintPathWithTexture[1];
+	width = (width || 10);
+	occurrence = (occurrence || 2);
+	strength = (strength || 0.5);
+	heightmap = (heightmap || g_Map.height);
+	
+	var clTempPath = createTileClass();
+	var targetReached = false;
+	var position = deepcopy(start);
+	while (!targetReached)
+	{
+		rectangularSmoothToHeight(position, width, width, targetHeight, strength, heightmap);
+		if (paintPath)
+		{
+			var placer = new ClumpPlacer(0.2 * width * width, 1, 1, 1, round(position.x), round(position.y));
+			var painter = [new TerrainPainter(pathTexture), paintClass(clTempPath)];
+			createArea(placer, painter);
+		}
+		
+		// Set vars for next loop
+		var angleToTarget = getAngle(position.x, position.y, target.x, target.y);
+		var angleOff = PI * (randFloat() - 0.5);
+		position.x += occurrence * cos(angleToTarget + angleOff);
+		position.y += occurrence * sin(angleToTarget + angleOff);
+		if (getDistance(position.x, position.y, target.x, target.y) < occurrence / 2)
+			targetReached = true;
+	}
+	return clTempPath;
+}
+
+
+/**
+*  Actually do stuff
+*/
+
+/**
+* Set height limits and water level by map size
+*/
+
+/**
+* Set target min and max height depending on map size to make average steepness about the same on all map sizes
+*/
+var heightRange = { "min": MIN_HEIGHT * (g_Map.size + 512) / 8192, "max": MAX_HEIGHT * (g_Map.size + 512) / 8192 };
+
+/**
+* Set average water coverage
+*/
+var averageWaterCoverage = 1/5; // NOTE: Since terrain generation is quite unpredictable actual water coverage might vary much with the same value
+var waterHeight = -MIN_HEIGHT + heightRange.min + averageWaterCoverage * (heightRange.max - heightRange.min); // Water height in environment and the engine
+var waterHeightAdjusted = waterHeight + MIN_HEIGHT; // Water height in RMGEN
+setWaterHeight(waterHeight);
+
+
+/**
+* Generate base terrain
+*/
+
+var initialReliefmap = undefined;
+var low = heightRange.min;
+var med = 0.5 * (heightRange.min + heightRange.max);
+var high = heightRange.max;
+/**
+* Island
+*/
+// initialReliefmap = [[low, low, low], [low, high, low], [low, low, low]];
+initialReliefmap = [[low, low, low, low], [low, high, high, low], [low, high, high, low], [low, low, low, low]];
+/**
+* Mountain
+*/
+// initialReliefmap = [[low, med, low], [med, high, med], [low, med, low]];
+/**
+* Lake
+*/
+// initialReliefmap = [[high, high, high], [high, low, high], [high, high, high]];
+// initialReliefmap = [[high, high, high, high], [high, low, low, high], [high, low, low, high], [high, high, high, high]];
+/**
+* Extreme Edges
+*/
+// initialReliefmap = [[high, med, low], [med, med, med], [low, med, high]];
+// initialReliefmap = [[high, med, med, low], [med, med, med, med], [med, med, med, med], [med, med, med, med], [low, med, med, high]];
+/**
+* Extreme Center
+*/
+// initialReliefmap = [[med, med, med, med], [med, high, low, med], [med, low, high, med], [med, med, med, med]];
+setBaseTerrainDiamondSquare(heightRange.min, heightRange.max, /*0.5*/ 0.8, initialReliefmap, g_Map.height);
+/**
+* Apply simple erosion
+*/
+for (var i = 0; i < 3; ++i)
+	globalSmoothHeightmap(0.5);
+rescaleHeightmap(heightRange.min, heightRange.max);
+
+
+/**
+* Setup biome and texture height limit
+*/
+
+/**
+* myBiome presets
+*/
+
+/**
+* Height presets
+*/
+var heighLimits = [
+	heightRange.min + 1/3 * (waterHeightAdjusted - heightRange.min), // 0 Deep water
+	heightRange.min + 2/3 * (waterHeightAdjusted - heightRange.min), // 1 Medium Water
+	heightRange.min + (waterHeightAdjusted - heightRange.min), // 2 Shallow water
+	waterHeightAdjusted + 1/8 * (heightRange.max - waterHeightAdjusted), // 3 Shore
+	waterHeightAdjusted + 2/8 * (heightRange.max - waterHeightAdjusted), // 4 Low ground
+	waterHeightAdjusted + 3/8 * (heightRange.max - waterHeightAdjusted), // 5 Player and path height
+	waterHeightAdjusted + 4/8 * (heightRange.max - waterHeightAdjusted), // 6 High ground
+	waterHeightAdjusted + 5/8 * (heightRange.max - waterHeightAdjusted), // 7 Lower forest border
+	waterHeightAdjusted + 6/8 * (heightRange.max - waterHeightAdjusted), // 8 Forest
+	waterHeightAdjusted + 7/8 * (heightRange.max - waterHeightAdjusted), // 9 Upper forest border
+	waterHeightAdjusted + (heightRange.max - waterHeightAdjusted)]; // 10 Hilltop
+
+/**
+* Add tile painting presets for each biome
+*/
+var dummyActor = "actor|props/special/common/waypoint_flag.xml";
+var myBiome = [];
+/**
+* temperate 1
+*/
+myBiome.push([]);
+/**
+* snowy 2
+*/
+myBiome.push([]);
+/**
+* desert 3
+*/
+myBiome.push([]);
+/**
+* Alpine 4
+*/
+myBiome.push([]);
+myBiome[myBiome.length - 1].push({ // 0 Deep water
+	"texture": ["shoreline_stoney_a"], "actor": [["gaia/fauna_fish", "actor|geology/stone_granite_boulder.xml"], 0.02],
+	"textureHS": ["alpine_mountainside"], "actorHS": [["gaia/fauna_fish"], 0.1] });
+myBiome[myBiome.length - 1].push({ // 1 Medium Water
+	"texture": ["shoreline_stoney_a", "alpine_shore_rocks"], "actor": [["actor|geology/stone_granite_boulder.xml"], 0.03],
+	"textureHS": ["alpine_mountainside"], "actorHS": [["actor|geology/stone_granite_boulder.xml"], 0.0] });
+myBiome[myBiome.length - 1].push({ // 2 Shallow water
+	"texture": ["alpine_shore_rocks"], "actor": [["actor|props/flora/reeds_pond_dry.xml", "actor|geology/stone_granite_large.xml", "actor|geology/stone_granite_med.xml", "actor|props/flora/reeds_pond_lush_b.xml"], 0.2],
+	"textureHS": ["alpine_mountainside"], "actorHS": [["actor|props/flora/reeds_pond_dry.xml", "actor|geology/stone_granite_med.xml"], 0.1] });
+myBiome[myBiome.length - 1].push({ // 3 Shore
+	"texture": ["alpine_shore_rocks_grass_50", "alpine_grass_rocky"], "actor": [["gaia/flora_tree_pine", "gaia/flora_bush_badlands", "actor|geology/highland1_moss.xml", "actor|props/flora/grass_soft_tuft_a.xml", "actor|props/flora/bush.xml"], 0.3],
+	"textureHS": ["alpine_mountainside"], "actorHS": [["actor|props/flora/grass_soft_tuft_a.xml"], 0.1] });
+myBiome[myBiome.length - 1].push({ // 4 Low ground
+	"texture": ["alpine_dirt_grass_50", "alpine_grass_rocky"], "actor": [["actor|geology/stone_granite_med.xml", "actor|props/flora/grass_soft_tuft_a.xml", "actor|props/flora/bush.xml", "actor|props/flora/grass_medit_flowering_tall.xml"], 0.2],
+	"textureHS": ["alpine_grass_rocky"], "actorHS": [["actor|geology/stone_granite_med.xml", "actor|props/flora/grass_soft_tuft_a.xml"], 0.1] });
+myBiome[myBiome.length - 1].push({ // 5 Player and path height
+	"texture": ["new_alpine_grass_c", "new_alpine_grass_b", "new_alpine_grass_d"], "actor": [["actor|geology/stone_granite_small.xml", "actor|props/flora/grass_soft_small.xml", "actor|props/flora/grass_medit_flowering_tall.xml"], 0.2],
+	"textureHS": ["alpine_grass_rocky"], "actorHS": [["actor|geology/stone_granite_small.xml", "actor|props/flora/grass_soft_small.xml"], 0.1] });
+myBiome[myBiome.length - 1].push({ // 6 High ground
+	"texture": ["new_alpine_grass_a", "alpine_grass_rocky"], "actor": [["actor|geology/stone_granite_med.xml", "actor|props/flora/grass_tufts_a.xml", "actor|props/flora/bush_highlands.xml", "actor|props/flora/grass_medit_flowering_tall.xml"], 0.2],
+	"textureHS": ["alpine_grass_rocky"], "actorHS": [["actor|geology/stone_granite_med.xml", "actor|props/flora/grass_tufts_a.xml"], 0.1] });
+myBiome[myBiome.length - 1].push({ // 7 Lower forest border
+	"texture": ["new_alpine_grass_mossy", "alpine_grass_rocky"], "actor": [["gaia/flora_tree_pine", "actor|props/flora/grass_tufts_a.xml", "gaia/flora_bush_berry", "gaia/flora_bush_berry", "gaia/flora_bush_berry", "actor|geology/highland2_moss.xml", "gaia/fauna_goat", "actor|props/flora/bush_tempe_underbrush.xml"], 0.3],
+	"textureHS": ["alpine_cliff_c"], "actorHS": [["actor|props/flora/grass_tufts_a.xml", "actor|geology/highland2_moss.xml"], 0.1] });
+myBiome[myBiome.length - 1].push({ // 8 Forest
+	"texture": ["alpine_forrestfloor"], "actor": [["gaia/flora_tree_pine", "gaia/flora_tree_pine", "gaia/flora_tree_pine", "gaia/flora_tree_pine", "actor|geology/highland2_moss.xml", "actor|props/flora/bush_highlands.xml"], 0.5],
+	"textureHS": ["alpine_cliff_c"], "actorHS": [["actor|geology/highland2_moss.xml", "actor|geology/stone_granite_med.xml"], 0.1] });
+myBiome[myBiome.length - 1].push({ // 9 Upper forest border
+	"texture": ["alpine_forrestfloor_snow", "new_alpine_grass_dirt_a"], "actor": [["gaia/flora_tree_pine", "actor|geology/snow1.xml"], 0.3],
+	"textureHS": ["alpine_cliff_b"], "actorHS": [["actor|geology/stone_granite_med.xml", "actor|geology/snow1.xml"], 0.1] });
+myBiome[myBiome.length - 1].push({ // 10 Hilltop
+	"texture": ["alpine_cliff_a"], "actor": [["actor|geology/highland1.xml"], 0.05],
+	"textureHS": ["alpine_cliff_c"], "actorHS": [["actor|geology/highland1.xml"], 0.0] });
+/**
+* medit 5
+*/
+myBiome.push([]);
+/**
+* savanah 6
+*/
+myBiome.push([]);
+/**
+* tropic 7
+*/
+myBiome.push([]);
+/**
+* autumn 8
+*/
+myBiome.push([]);
+
+/**
+* Set random biome
+*/
+while (biomeID != 4)
+	randomizeBiome();
+log("biomeID = " + biomeID); // DEBUG
+
+if (biomeID == 4)
+{
+	g_Environment.Fog.FogColor = { "r": 0.8, "g": 0.8, "b": 0.8, "a": 0 };
+	g_Environment.Water.WaterBody.Colour = { "r" : 0.0, "g" : 0.05, "b" : 0.1, "a" : 0 };
+	g_Environment.Water.WaterBody.Murkiness = 0.5;
+	rbt7 = rbt8;
+	rbt8 = rbt1
+	rbt1 = [rbt9[1]];
+	rbt9 = [rbt9[0]];
+}
+if (biomeID == 6)
+	rbt9 = [rbt9[1]];
+if (biomeID == 8)
+	rbt9 = rbt6;
+
+
+/**
+* Place start locations and apply terrain texture and decorative props by height
+*/
+
+/**
+* Get start locations
+*/
+var startLocations = getStartLocationsByHeightmap({ "min": heighLimits[4], "max": heighLimits[5] });
+var playerHeight = (heighLimits[4] + heighLimits[5]) / 2;
+
+/**
+* Place start locations
+*/
+for (var p = 0; p < g_MapSettings.PlayerData.length - 1; ++p)
+{
+	rectangularSmoothToHeight(startLocations[p], 35, 35, playerHeight, 0.8);
+	placeCivDefaultEntities(startLocations[p].x, startLocations[p].y, p + 1, BUILDING_ANGlE, { "iberWall": true });
+	// Place resources at start locations
+	var uDist = 8;
+	var uSpace = 1.2;
+	for (var j = 1; j <= 4; ++j)
+	{
+		var uAngle = BUILDING_ANGlE - PI * (2-j) / 2;
+		var count = 4;
+		for (var numberofentities = 0; numberofentities < count; ++numberofentities)
+		{
+			var ux = startLocations[p].x + uDist * cos(uAngle) + numberofentities * uSpace * cos(uAngle + PI/2) - (0.75 * uSpace * floor(count / 2) * cos(uAngle + PI/2));
+			var uz = startLocations[p].y + uDist * sin(uAngle) + numberofentities * uSpace * sin(uAngle + PI/2) - (0.75 * uSpace * floor(count / 2) * sin(uAngle + PI/2));
+			if (j % 2 == 0)
+				placeObject(ux, uz, rbe6, 0, randFloat(0, 2*PI));
+			else
+				placeObject(ux, uz, rbe4, 0, randFloat(0, 2*PI));
+		}
+	}
+	ux = startLocations[p].x + 10 * cos(BUILDING_ANGlE + PI / 4);
+	uz = startLocations[p].y + 10 * sin(BUILDING_ANGlE + PI / 4);
+	// placeObject(ux, uz, rbe11, 0, randFloat(0, 2*PI));
+	ux = startLocations[p].x + 10 * cos(BUILDING_ANGlE - 3 * PI / 4);
+	uz = startLocations[p].y + 10 * sin(BUILDING_ANGlE - 3 * PI / 4);
+	// placeObject(ux, uz, rbe13, 0, randFloat(0, 2*PI));
+}
+
+/**
+* Add further stone and metal mines
+*/
+distributeEntitiesByHeight({ "min": heighLimits[4], "max": heighLimits[5] }, startLocations);
+
+/**
+* Add paths
+*/
+var pathTerrainClasseIDs = [];
+var pathPointDist = 3;
+var startLocationOrder = getOrderOfPointsForShortestClosePath(startLocations);
+// for (var i = 0; i < startLocationOrder.length; ++i)
+// {
+	// var start = startLocations[startLocationOrder[i]];
+	// var target = startLocations[startLocationOrder[(i + 1) % startLocationOrder.length]];
+	// pathTerrainClasseIDs.push(placeRandomPathToHeight(start, [true, "road_rome_a"], target, playerHeight, 10, pathPointDist, 0.2));
+// }
+
+/**
+* Calculate slope map (Not entirely sure if correct or slopeMap is the correct term)
+*/
+var slopeMap = getSlopeMap();
+
+/**
+* Calculate tileCenteredHeightMap (This has nothing to to with TILE_CENTERED_HEIGHT_MAP which should be false (default) for this map to work properly)
+*/
+var tchm = getTileCenteredHeightmap();
+
+/**
+* Divide tiles in areas by height and avoid paths
+*/
+var areas = [];
+var pathAreas = [];
+for (var i = 0; i < pathTerrainClasseIDs.length; ++i)
+	pathAreas.push([]);
+for (var h = 0; h < heighLimits.length; ++h)
+	areas.push([]);
+for (var x = 0; x < tchm.length; ++x)
+{
+	for (var y = 0; y < tchm[0].length; ++y)
+	{
+		var isPath = false;
+		for (var i = 0; i < pathTerrainClasseIDs.length; ++i)
+		{
+			if (getTileClass(pathTerrainClasseIDs[i]).countMembersInRadius(x, y, 0.5))
+			{
+				pathAreas[i].push({ "x": x, "y": y });
+				isPath = true;
+				break;
+			}
+		}
+		if (!isPath)
+		{
+			var minHeight = heightRange.min;
+			for (var h = 0; h < heighLimits.length; ++h)
+			{
+				if (tchm[x][y] >= minHeight && tchm[x][y] <= heighLimits[h])
+				{
+					areas[h].push({ "x": x, "y": y });
+					break;
+				}
+				else
+					minHeight = heighLimits[h];
+			}
+		}
+	}
+}
+
+/**
+* Get max slope of each area
+*/
+var minSlope = new Array(areas.length);
+var maxSlope = new Array(areas.length);
+for (var h = 0; h < heighLimits.length; ++h)
+{
+	minSlope[h] = Infinity;
+	maxSlope[h] = 0;
+	for (var t = 0; t < areas[h].length; ++t)
+	{
+		var x = areas[h][t].x;
+		var y = areas[h][t].y;
+		var slope = slopeMap[x][y];
+		if (slope > maxSlope[h])
+			maxSlope[h] = slope;
+		if (slope < minSlope[h])
+			minSlope[h] = slope;
+	}
+}
+
+/**
+* Paint areas by height and slope
+*/
+for (var h = 0; h < heighLimits.length; ++h)
+{
+	for (var t = 0; t < areas[h].length; ++t)
+	{
+		var x = areas[h][t].x;
+		var y = areas[h][t].y;
+		var actor = undefined;
+		if (slopeMap[x][y] < 0.5 * (minSlope[h] + maxSlope[h]))
+		{
+			var texture = myBiome[biomeID - 1][h].texture[randInt(myBiome[biomeID - 1][h].texture.length)];
+			if (randFloat() < myBiome[biomeID - 1][h].actor[1])
+				actor = myBiome[biomeID - 1][h].actor[0][randInt(myBiome[biomeID - 1][h].actor[0].length)];
+		}
+		else
+		{
+			var texture = myBiome[biomeID - 1][h].textureHS[randInt(myBiome[biomeID - 1][h].textureHS.length)];
+			if (randFloat() < myBiome[biomeID - 1][h].actorHS[1])
+				actor = myBiome[biomeID - 1][h].actorHS[0][randInt(myBiome[biomeID - 1][h].actorHS[0].length)];
+		}
+		g_Map.setTexture(x, y, texture);
+		if (actor)
+			placeObject(x + 0.5, y + 0.5, actor, 0, randFloat() * TWO_PI);
+	}
+}
+
+
+/**
+* DEBUG Collision detection START
+*/
+// for (var ox = 0; ox < collision.obstructionMap.length; ++ox)
+// {
+	// for (var oy = 0; oy < collision.obstructionMap[ox].length; ++oy)
+	// {
+		// if (collision.obstructionMap[ox][oy])
+		// {
+			// var x = (ox + 0.5) / CELL_SIZE * collision.obstructionGridSizeInMeters;
+			// var y = (oy + 0.5) / CELL_SIZE * collision.obstructionGridSizeInMeters;
+			// // log("ox = " + ox + ", oy = " + oy + ", x = " + x + ", y = " + y);
+			// if (g_Map.validT(x, y))
+				// placeObject(x, y, "actor|geology/stone_granite_small.xml", 0, randFloat() * TWO_PI);
+			// else
+				// warn("Obstruction cell {x: " + uneval(ox) + ", y: " + uneval(oy) + "} corresponds to a tile outside the map (size = " + uneval(g_Map.height.length) + "): {x: " + uneval(x) + ", y: " + uneval(y) + "}");
+		// }
+	// }
+// }
+/**
+* DEBUG Collision detection END
+*/
+
+/**
+* DEBUG Stop Timer
+*/
+log("Map generation time: " + (new Date().getTime() - genStartTime))
+
+/**
+* Export map data
+*/
+ExportMap();
+
+/**
+* DEBUG Entity IDs START
+*/
+// for (var i = 0; i < g_Map.objects.length; ++i)
+// {
+	// var id = g_Map.objects[i].id;
+	// if (i + 150 != id)
+		// log("The " + i + "-th object (should be ID " + uneval(i + 150) + ") has ID " + id);
+// }
+/**
+* DEBUG Entity IDs END
+*/
Index: binaries/data/mods/public/maps/random/realisticTerrainDemo.json
===================================================================
--- binaries/data/mods/public/maps/random/realisticTerrainDemo.json	(revision 0)
+++ binaries/data/mods/public/maps/random/realisticTerrainDemo.json	(working copy)
@@ -0,0 +1,12 @@
+{
+	"settings" : {
+		"Name" : "Realistic Terrain Demo",
+		"Script" : "realisticTerrainDemo.js",
+		"Description" : "A map to demonstrate playability of more realistic random terrain.",
+		"CircularMap" : false,
+		"BaseTerrain" : "whiteness",
+		"BaseHeight" : 0,
+		"Keywords": ["demo"],
+		"XXXXXX" : "Optionally define other things here, like we would for a scenario"
+	}
+}
\ No newline at end of file
Index: binaries/data/mods/public/maps/random/rmgen/heightmap_manipulation.js
===================================================================
--- binaries/data/mods/public/maps/random/rmgen/heightmap_manipulation.js	(revision 0)
+++ binaries/data/mods/public/maps/random/rmgen/heightmap_manipulation.js	(working copy)
@@ -0,0 +1,472 @@
+/**
+*	Heightmap manipulation functionality
+*
+*	A heightmapt is an array of width arrays of height floats
+*	Width and height is normally mapSize+1 (Number of vertices is one bigger than number of tiles in each direction)
+*	The default heightmap is g_Map.height (See the Map object)
+*
+*	NOTE (ambiguous naming/potential confusion):
+*		For using this heightmap functionalities it is VITAL that TILE_CENTERED_HEIGHT_MAP = false (default)!
+*		Otherwise TILE_CENTERED_HEIGHT_MAP has nothing to do with any tile centered heightmap in this library!
+*		All tile centered heightmaps in this module are temporary objects only and should never replace g_Map.height!
+*		(Tile centered heightmaps are one less in width and hight than heightmaps used by the engine)
+*		(Multiple conversions will lead to strange smoothing effects at best and potentially break the map entirely!)
+*		In the long run TILE_CENTERED_HEIGHT_MAP should be removed and g_Map.height should never be tile centered...
+*/
+
+/**
+* getMinAndMaxHeight
+*	Optionally takes a heightmap, default is g_Map.height
+*	Returns the minimum and maximum heights present in this heightmap (an associative array of the form {"min": minHeight, "max": maxHeight})
+*/
+function getMinAndMaxHeight(heightmap)
+{
+	heightmap = (heightmap || g_Map.height)
+	var height = {};
+	height.min = Infinity;
+	height.max = - Infinity;
+	for (var x = 0; x < heightmap.length; ++x)
+	{
+		for (var y = 0; y < heightmap[x].length; ++y)
+		{
+			if (heightmap[x][y] < height.min)
+				height.min = heightmap[x][y];
+			else if (heightmap[x][y] > height.max)
+				height.max = heightmap[x][y];
+		}
+	}
+	return height;
+}
+
+/**
+* rescaleHeightmap
+*	Takes:
+*		Optional minHeight(float), minimum height that should be used for the resulting heightmap, default is MIN_HEIGHT
+*		Optional maxHeight(float), maximum height that should be used for the resulting heightmap, default is MAX_HEIGHT
+*		Optional heightmap, default is g_Map.height
+*	Rescales the heightmap so its minimum and maximum height is as the arguments told (preserving it's global shape)
+*/
+function rescaleHeightmap(minHeight, maxHeight, heightmap)
+{
+	minHeight = (minHeight || MIN_HEIGHT);
+	maxHeight = (maxHeight || MAX_HEIGHT);
+	heightmap = (heightmap || g_Map.height);
+	
+	var oldHeightRange = getMinAndMaxHeight(heightmap);
+	var max_x = heightmap.length;
+	var max_y = heightmap[0].length;
+	for (var x = 0; x < max_x; ++x)
+		for (var y = 0; y < max_y; ++y)
+			heightmap[x][y] = minHeight + (heightmap[x][y] - oldHeightRange.min) / (oldHeightRange.max - oldHeightRange.min) * (maxHeight - minHeight);
+}
+
+/**
+* getInclineMap
+*	Optionally takes a heightmap, default is g_Map.height
+*	Returns an inclination map corresponding to the tiles between the heightmaps vertices:
+*		array of heightmap width-1 arrays of height-1 vectors (associative arrays) of the from:
+*			{"x": x_slope, "y": y_slope] so a 2D Vector pointing to the hightest incline (with the length the incline in the vectors direction)
+* NOTE: The x and y coordinates of a tile in the terrain texture map correspond to those of the inclination map
+*/
+function getInclineMap(heightmap)
+{
+	heightmap = (heightmap || g_Map.height);
+	var max_x = heightmap.length - 1;
+	var max_y = heightmap[0].length - 1;
+	var inclineMap = [];
+	for (var x = 0; x < max_x; ++x)
+	{
+		inclineMap[x] = [];
+		for (var y = 0; y < max_y; ++y)
+		{
+			var dx = heightmap[x + 1][y] - heightmap[x][y];
+			var dy = heightmap[x][y + 1] - heightmap[x][y];
+			var next_dx = heightmap[x + 1][y + 1] - heightmap[x][y + 1];
+			var next_dy = heightmap[x + 1][y + 1] - heightmap[x + 1][y];
+			inclineMap[x][y] = {"x": 0.5 * (dx + next_dx), "y": 0.5 * (dy + next_dy)};
+		}
+	}
+	return inclineMap;
+}
+
+/**
+* getSlopeMap
+*	Optionally takes an inclineMap, default is getInclineMap(g_Map.height)
+*	Returns a slope map (same form as the a heightmap with one less width and height)
+* NOTES:
+*	Not normalized. Only returns the steepness (float), not the direction of incline.
+*	The x and y coordinates of a tile in the terrain texture map correspond to those of the slope map
+*/
+function getSlopeMap(inclineMap)
+{
+	inclineMap = (inclineMap || getInclineMap(g_Map.height));
+	var max_x = inclineMap.length;
+	var slopeMap = new Array(max_x);
+	for (var x = 0; x < max_x; ++x)
+	{
+		var max_y = inclineMap[x].length;
+		slopeMap[x] = new Float32Array(max_y);
+		for (var y = 0; y < max_y; ++y)
+			slopeMap[x][y] = Math.pow(inclineMap[x][y].x * inclineMap[x][y].x + inclineMap[x][y].y * inclineMap[x][y].y, 0.5);
+	}
+	return slopeMap;
+}
+
+/**
+* getTileCenteredHeightmap
+*	Optionally takes a heightmap, default is g_Map.height
+*	Returns an approximation of the heights of the tiles between the vertices, a tile centered heightmap
+*	NOTE:
+*		A tile centered heightmap is one smaller in width and height than an ordinary heightmap
+*		It is meant to e.g. texture a map by height (x/y coordinates correspond to those of the terrain texture map)
+*		Don't use this to override g_Map height (Potentially breaks the map)!
+*/
+function getTileCenteredHeightmap(heightmap)
+{
+	heightmap = (heightmap || g_Map.height);
+	var max_x = heightmap.length - 1;
+	var max_y = heightmap[0].length - 1;
+	var tchm = new Array(max_x);
+	for (var x = 0; x < max_x; ++x)
+	{
+		tchm[x] = new Float32Array(max_y);
+		for (var y = 0; y < max_y; ++y)
+		{
+			tchm[x][y] = 0.25 * (heightmap[x][y] + heightmap[x + 1][y] + heightmap[x][y + 1] + heightmap[x + 1][y + 1]);
+		}
+	}
+	return tchm;
+}
+
+/**
+*	getStartLocationsByHeightmap
+*
+*	Description:
+*		Get start location with the largest minimum distance between players
+*	Takes
+*		hightRange		An associative array with keys "min" and "max" each containing a float (the height range start locations are allowed)
+*		maxTries		Optional, default is 1000, an integer, how often random player distributions are rolled to be compared
+*		minDistToBorder	Optional, default is 20, an integer, how far start locations have to be away from the map border
+*		numberOfPlayers	Optional, default is g_MapSettings.PlayerData.length, an integer, how many start locations should be placed
+*		Heightmap		Optional, default is g_Map.height, the heightmap for the start locations to be placed on
+*	Returns
+*		An array of 2D points (arrays of length 2)
+*/
+function getStartLocationsByHeightmap(hightRange, maxTries, minDistToBorder, numberOfPlayers, heightmap)
+{
+	maxTries = (maxTries || 1000);
+	minDistToBorder = (minDistToBorder || 20);
+	numberOfPlayers = (numberOfPlayers || g_MapSettings.PlayerData.length);
+	heightmap = (heightmap || g_Map.height);
+	
+	var validStartLoc = [];
+	for (var x = minDistToBorder; x < heightmap.length - minDistToBorder; ++x)
+		for (var y = minDistToBorder; y < heightmap[0].length - minDistToBorder; ++y)
+			if (heightmap[x][y] > hightRange.min && heightmap[x][y] < hightRange.max) // Has the right hight
+				validStartLoc.push({"x": x, "y": y});
+	
+	var maxMinDist = 0;
+	for (var tries = 0; tries < maxTries; ++tries)
+	{
+		var startLoc = [];
+		var minDist = heightmap.length;
+		for (var p = 0; p < numberOfPlayers; ++p)
+			startLoc.push(validStartLoc[randInt(validStartLoc.length)]);
+		for (var p1 = 0; p1 < numberOfPlayers - 1; ++p1)
+		{
+			for (var p2 = p1 + 1; p2 < numberOfPlayers; ++p2)
+			{
+				var dist = getDistance(startLoc[p1].x, startLoc[p1].y, startLoc[p2].x, startLoc[p2].y);
+				if (dist < minDist)
+					minDist = dist;
+			}
+		}
+		if (minDist > maxMinDist)
+		{
+			maxMinDist = minDist;
+			var finalStartLoc = startLoc;
+		}
+	}
+	
+	return finalStartLoc;
+}
+
+/**
+*	distributeEntitiesByHeight
+*	Takes
+*		hightRange		An associative array with keys "min" and "max" each containing a float (the height range start locations are allowed)
+*		startLoc		An array of 2D points (arrays of length 2)
+*		heightmap		Optional, default is g_Map.height, an array of (map width) arrays of (map depth) floats
+*		entityList		Array of entities/actors (strings to be placed with placeObject())
+*		maxTries		Optional, default is 1000, an integer, how often random player distributions are rolled to be compared
+*		minDistance		Optional, default is 30, an integer, how far start locations have to be away from start locations and the map border
+*	Returns
+*		An array of 2D points (arrays of length 2)
+*/
+function distributeEntitiesByHeight(hightRange, startLoc, entityList, maxTries, minDistance, heightmap)
+{
+	entityList = (entityList || [rbe11, rbe13]);
+	maxTries = (maxTries || 1000);
+	minDistance = (minDistance || 30);
+	heightmap = (heightmap || g_Map.height);
+	
+	var placements = deepcopy(startLoc);
+	var validTiles = [];
+	for (var x = minDistance; x < heightmap.length - minDistance; ++x)
+		for (var y = minDistance; y < heightmap[0].length - minDistance; ++y)
+			if (heightmap[x][y] > hightRange.min && heightmap[x][y] < hightRange.max) // Has the right hight
+				validTiles.push({"x": x, "y": y});
+	
+	for (var tries = 0; tries < maxTries; ++tries)
+	{
+		var tile = validTiles[randInt(validTiles.length)];
+		var isValid = true;
+		for (var p = 0; p < placements.length; ++p)
+		{
+			if (getDistance(placements[p].x, placements[p].y, tile.x, tile.y) < minDistance)
+			{
+				isValid = false;
+				break;
+			}
+		}
+		if (isValid)
+		{
+			placeObject(tile.x, tile.y, entityList[randInt(entityList.length)], 0, randFloat(0, 2*PI));
+			// placeObject(tile[0], tile[1], "actor|geology/decal_stone_medit_b.xml", 0, randFloat(0, 2*PI));
+			placements.push(tile);
+		}
+	}
+}
+
+/**
+*	setBaseTerrainDiamondSquare
+*
+*	Description:
+*		Sets the heightmap to a relatively realistic shape.
+*	Takes:
+*		minHeight			Optional, Float, Default is the absolute possible minimum height
+*							Minimum height that can occur in the resulting heightmap
+*		maxHeight			Optional, Float, Default is the absolute possible maximum height
+*							Maximum height that can occur in the resulting heightmap
+*		smoothness			Optional, Float between 0 (rough) to 1 (smooth), Default is 0.5
+*							Lower values (rough) will generate more local structures (but should be smoothed e.g. with erosion later)
+*		initialHeightmap	Optional, Array of width Arrays of depth Floats (usually a small square heightmap e.g. 2x2)
+*							Sets some initial heights at the edges (square heightmap of size 2) or more more specifically with bigger initial heightmaps
+*		heightmap			Optional, Array of width Arrays of depth Floats (a heightmap), Default is g_Map.height
+*							The heightmap that will be set by this function
+*	Returns nothing
+*	NOTES:
+*		min/maxHeight will not necessarily be present in the heightmap
+*		This function only supports rectangular heightmaps.
+*			This means that e.g. the edges (given by initialHeightmap) will not be in the playable map area in circular maps.
+*		The function doubles the size of the initial heightmap (if given, else a random 2x2 one) until it's big enough.
+*			Then the extend is cut. So the impact and scale of the initial heightmap depends on its size and the target map size.
+*/
+function setBaseTerrainDiamondSquare(minHeight, maxHeight, smoothness, initialHeightmap, heightmap)
+{
+	// Make some arguments optional
+	minHeight = (minHeight || MIN_HEIGHT);
+	maxHeight = (maxHeight || MAX_HEIGHT);
+	var heightRange = maxHeight - minHeight;
+	if (heightRange <= 0)
+		warn("setBaseTerrainDiamondSquare: heightRange < 0");
+	smoothness = (smoothness || 0.5);
+	initialHeightmap = (initialHeightmap || [[randFloat(minHeight / 2, maxHeight / 2), randFloat(minHeight / 2, maxHeight / 2)], [randFloat(minHeight / 2, maxHeight / 2), randFloat(minHeight / 2, maxHeight / 2)]]);
+	heightmap = (heightmap || g_Map.height);
+	
+	var offset = heightRange / 2;
+	
+	// Double initialHeightmap width until target width is reached (diamond square method)
+	while (initialHeightmap.length < heightmap.length)
+	{
+		var newHeightmap = [];
+		var oldWidth = initialHeightmap.length;
+		// Square
+		for (var x = 0; x < 2 * oldWidth - 1; ++x)
+		{
+			newHeightmap.push([]);
+			for (var y = 0; y < 2 * oldWidth - 1; ++y)
+			{
+				if (x % 2 == 0 && y % 2 == 0) // Old tile
+					newHeightmap[x].push(initialHeightmap[x/2][y/2]);
+				else if (x % 2 == 1 && y % 2 == 1) // New tile with diagonal old tile neighbors
+				{
+					newHeightmap[x].push((initialHeightmap[(x-1)/2][(y-1)/2] + initialHeightmap[(x+1)/2][(y-1)/2] + initialHeightmap[(x-1)/2][(y+1)/2] + initialHeightmap[(x+1)/2][(y+1)/2]) / 4);
+					newHeightmap[x][y] += (newHeightmap[x][y] - minHeight) / heightRange * randFloat(-offset, offset)
+				}
+				else // New tile with straight old tile neighbors
+					newHeightmap[x].push(undefined); // Define later
+			}
+		}
+		// Diamond
+		for (var x = 0; x < 2 * oldWidth - 1; ++x)
+		{
+			for (var y = 0; y < 2 * oldWidth - 1; ++y)
+			{
+				if (newHeightmap[x][y] === undefined)
+				{
+					if (x > 0 && x + 1 < newHeightmap.length - 1 && y > 0 && y + 1 < newHeightmap.length - 1) // Not a border tile
+					{
+						newHeightmap[x][y] = (newHeightmap[x+1][y] + newHeightmap[x][y+1] + newHeightmap[x-1][y] + newHeightmap[x][y-1]) / 4;
+						newHeightmap[x][y] += (newHeightmap[x][y] - minHeight) / heightRange * randFloat(-offset, offset)
+					}
+					else if (x < newHeightmap.length - 1 && y > 0 && y < newHeightmap.length - 1) // Left border
+					{
+						newHeightmap[x][y] = (newHeightmap[x+1][y] + newHeightmap[x][y+1] + newHeightmap[x][y-1]) / 3;
+						newHeightmap[x][y] += (newHeightmap[x][y] - minHeight) / heightRange * randFloat(-offset, offset)
+					}
+					else if (x > 0 && y > 0 && y < newHeightmap.length - 1) // Right border
+					{
+						newHeightmap[x][y] = (newHeightmap[x][y+1] + newHeightmap[x-1][y] + newHeightmap[x][y-1]) / 3;
+						newHeightmap[x][y] += (newHeightmap[x][y] - minHeight) / heightRange * randFloat(-offset, offset)
+					}
+					else if (x > 0 && x < newHeightmap.length - 1 && y < newHeightmap.length - 1) // Bottom border
+					{
+						newHeightmap[x][y] = (newHeightmap[x+1][y] + newHeightmap[x][y+1] + newHeightmap[x-1][y]) / 3;
+						newHeightmap[x][y] += (newHeightmap[x][y] - minHeight) / heightRange * randFloat(-offset, offset)
+					}
+					else if (x > 0 && x < newHeightmap.length - 1 && y > 0) // Top border
+					{
+						newHeightmap[x][y] = (newHeightmap[x+1][y] + newHeightmap[x-1][y] + newHeightmap[x][y-1]) / 3;
+						newHeightmap[x][y] += (newHeightmap[x][y] - minHeight) / heightRange * randFloat(-offset, offset)
+					}
+				}
+			}
+		}
+		initialHeightmap = deepcopy(newHeightmap);
+		offset /= Math.pow(2, smoothness);
+	}
+	
+	// Cut initialHeightmap to fit target width
+	var shift = [floor((newHeightmap.length - heightmap.length) / 2), floor((newHeightmap[0].length - heightmap[0].length) / 2)];
+	for (var x = 0; x < heightmap.length; ++x)
+		for (var y = 0; y < heightmap[0].length; ++y)
+			heightmap[x][y] = newHeightmap[x][y];
+}
+
+/**
+*	globalSmoothHeightmap
+*
+*	Takes:
+*		strength	Optional, Float between 0 (no effect) and 1 (2 appending tiles will be set to roughly the same height), default is 0.8
+*					How strong the smooth effect should be
+*		heightmap	Optional, Array of width Arrays of depth Floats (a heightmap), Default is g_Map.height
+*					The heightmap to be smoothed
+*	Returns nothing
+*	NOTES:
+*		Strength values >0.9 might result in interference.
+*		To strengthen the smooth effect it's better to apply it multiple times than using high strength values.
+*/
+function globalSmoothHeightmap(strength, heightmap)
+{
+	strength = (strength || 0.8); // 0 to 1
+	heightmap = (heightmap || g_Map.height);
+	
+	var referenceHeightmap = deepcopy(heightmap);
+	// var map = [[1, 0], [0, 1], [-1, 0], [0, -1]]; // faster
+	var map = [[1, 0], [1, 1], [0, 1], [-1, 1], [-1, 0], [-1, -1], [0, -1], [1, -1]]; // smoother
+	var max_x = heightmap.length;
+	var max_y = heightmap[0].length;
+	for (var x = 0; x < max_x; ++x)
+	{
+		for (var y = 0; y < max_y; ++y)
+		{
+			for (var i = 0; i < map.length; ++i)
+			{
+				var mapX = x + map[i][0];
+				var mapY = y + map[i][1];
+				if (mapX >= 0 && mapX < max_x && mapY >= 0 && mapY < max_y)
+					heightmap[x][y] += strength / map.length * (referenceHeightmap[mapX][mapY] - referenceHeightmap[x][y]);
+			}
+		}
+	}
+}
+
+/**
+*	rectangularSmoothToHeight
+*
+*	Description:
+*		Pushes a rectangular area towards a given height smoothing it into the original terrain
+*	Takes:
+*		center			Associative Array with keys x and y containing Floats (the x/y coordinates of the center)
+*		dx/dy			Float, Distance from the center in x/y direction the rectangle ends (half width/depth)
+*		targetHeight	Float, Height the center of the rectangle will be pushed to
+*		strength		Float between 0 (no change) to 1 (center set to target height), how strong the height is pushed
+*		heightmap		Optional, Array of width Arrays of depth Floats (a heightmap), Default is g_Map.height
+*						The heightmap to be manipulated
+*	Returns nothing
+*	NOTES:
+*		The window function to determine the smooth is not exactly a gaussian to ensure smooth edges.
+*		The optimal function is not clear so several working ones are left in the function (documented out)
+*/
+function rectangularSmoothToHeight(center, dx, dy, targetHeight, strength, heightmap)
+{
+	var x = round(center.x);
+	var y = round(center.y);
+	dx = round(dx);
+	dy = round(dy);
+	strength = (strength || 1);
+	heightmap = (heightmap || g_Map.height);
+	
+	var heightmapWin = [];
+	for (var wx = 0; wx < 2 * dx + 1; ++wx)
+	{
+		heightmapWin.push([]);
+		for (var wy = 0; wy < 2 * dy + 1; ++wy)
+		{
+			var actualX = x - dx + wx;
+			var actualY = y - dy + wy;
+			if (actualX >= 0 && actualX < heightmap.length - 1 && actualY >= 0 && actualY < heightmap[0].length - 1) // Is in map
+				heightmapWin[wx].push(heightmap[actualX][actualY]);
+			else
+				heightmapWin[wx].push(targetHeight);
+		}
+	}
+	for (var wx = 0; wx < 2 * dx + 1; ++wx)
+	{
+		for (var wy = 0; wy < 2 * dy + 1; ++wy)
+		{
+			var actualX = x - dx + wx;
+			var actualY = y - dy + wy;
+			if (actualX >= 0 && actualX < heightmap.length - 1 && actualY >= 0 && actualY < heightmap[0].length - 1) // Is in map
+			{
+				// // Window function rectangle
+				// var scaleX = 1;
+				// var scaleY = 1;
+				// // Window function triangle
+				// var scaleX = min(min(wx / dx, (2 * dx + 1 - wx) / dx), 1);
+				// var scaleY = min(min(wy / dy, (2 * dy + 1 - wy) / dy), 1);
+				// // Window function trapeze
+				// var scaleX = min(min(1.3 * wx / dx, 1.3 * (2 * dx + 1 - wx) / dx), 1);
+				// var scaleY = min(min(1.3 * wy / dy, 1.3 * (2 * dy + 1 - wy) / dy), 1);
+				// // Window function simple sine (range PI)
+				// var scaleX = sin(wx * PI / (2 * dx + 1));
+				// var scaleY = sin(wy * PI / (2 * dy + 1));
+				// // Window function cosine (range 2*PI)
+				// var scaleX = (cos((wx - (2 * dx + 1) / 2) * 2 * PI / (2 * dx + 1)) + 1) / 2;
+				// var scaleY = (cos((wy - (2 * dy + 1) / 2) * 2 * PI / (2 * dy + 1)) + 1) / 2;
+				// // Window function polynomial 2nd degree (BEST SINGLE SO FAR)
+				var scaleX = 1 - (wx / dx - 1) * (wx / dx - 1);
+				var scaleY = 1 - (wy / dy - 1) * (wy / dy - 1);
+				// // Window function polynomial 4th degree
+				// var scaleX = (wx / dx - 1) * (wx / dx - 1) * (wx / dx - 1) * (wx / dx - 1) - 2 * (wx / dx - 1) * (wx / dx - 1) + 1;
+				// var scaleY = (wy / dy - 1) * (wy / dy - 1) * (wy / dy - 1) * (wy / dy - 1) - 2 * (wy / dy - 1) * (wy / dy - 1) + 1;
+				// COMBINATIONS
+				// // Window function arithmetic mean of simple sine (range PI) and trapeze
+				// var scaleX = (sin(wx * PI / (2 * dx + 1)) + min(min(2.1 * wx / dx, 2.1 * (2 * dx + 1 - wx) / dx), 1)) / 2;
+				// var scaleY = (sin(wy * PI / (2 * dy + 1)) + min(min(2.1 * wy / dy, 2.1 * (2 * dy + 1 - wy) / dy), 1)) / 2;
+				// // Window function arithmetic mean of cosine (range 2*PI) and trapeze
+				// var scaleX = ((cos((wx - (2 * dx + 1) / 2) * 2 * PI / (2 * dx + 1)) + 1) / 2 + min(min(5 * wx / dx, 5 * (2 * dx + 1 - wx) / dx), 1)) / 2;
+				// var scaleY = ((cos((wy - (2 * dy + 1) / 2) * 2 * PI / (2 * dy + 1)) + 1) / 2 + min(min(5 * wy / dy, 5 * (2 * dy + 1 - wy) / dy), 1)) / 2;
+				// // Window function arithmetic mean of polynomial 2nd degree and trapeze (BEST COMBINATION SO FAR)
+				// var scaleX = (1 - (wx / dx - 1) * (wx / dx - 1) + min(min(3 * wx / dx, 3 * (2 * dx + 1 - wx) / dx), 1)) / 2;
+				// var scaleY = (1 - (wy / dy - 1) * (wy / dy - 1) + min(min(3 * wy / dy, 3 * (2 * dy + 1 - wy) / dy), 1)) / 2;
+				
+				if (scaleX < 0 || scaleY < 0 || scaleX > 1 || scaleY > 1) // DEBUG
+					warn("rectangularSmoothToHeight: Scale < 0 or > 1: scaleX = " + scaleX + ", scaleY = " + scaleY); // DEBUG
+				heightmap[actualX][actualY] = heightmapWin[wx][wy] + strength * scaleX * scaleY * (targetHeight - heightmapWin[wx][wy]);
+				// g_Map.setTexture(actualX, actualY, "red"); // DEBUG
+			}
+		}
+	}
+}
Index: binaries/data/mods/public/maps/random/rmgen/library.js
===================================================================
--- binaries/data/mods/public/maps/random/rmgen/library.js	(revision 17723)
+++ binaries/data/mods/public/maps/random/rmgen/library.js	(working copy)
@@ -1,22 +1,38 @@
-
-/////////////////////////////////////////////////////////////////////////////////////////////
-//	Constant definitions
-/////////////////////////////////////////////////////////////////////////////////////////////
-
+/**
+ * Constant definitions
+ */
 const PI = Math.PI;
-const TWO_PI = 2 * Math.PI;
+const TWO_PI = 2 * Math.PI; // mathematically known as 'tau'
 const TERRAIN_SEPARATOR = "|";
-const SEA_LEVEL = 20.0;
+const SEA_LEVEL = 160.0;
 const CELL_SIZE = 4;
 const HEIGHT_UNITS_PER_METRE = 92;
 const MIN_MAP_SIZE = 128;
 const MAX_MAP_SIZE = 512;
 const FALLBACK_CIV = "athen";
 
-/////////////////////////////////////////////////////////////////////////////////////////////
-//	Utility functions
-/////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Constants needed for heightmap_manipulation.js
+ */
+const MAX_HEIGHT_RANGE = 0xFFFF / HEIGHT_UNITS_PER_METRE // Engine limit, Roughly 700 meters
+const MIN_HEIGHT = - SEA_LEVEL;
+const MAX_HEIGHT = MAX_HEIGHT_RANGE - SEA_LEVEL;
+/**
+ * Entity template structure keys that might change, for easier mod support
+ */
+const CIV_PLACEHOLDER_STRING = "{civ}";
+const START_ENTITY_KEYS = ["StartEntities"];
+const START_ENTITY_TEMPLATE_KEYS = ["Template"];
+const BUILDER_TEMPLATEPATH_KEYS = ["Builder", "Entities", "_string"];
+const PRODUCTION_TEMPLATEPATH_KEYS = ["ProductionQueue", "Entities", "_string"];
+const WALLSET_KEYS = ["WallSet"];
+const BUILDING_KEYS = ["Obstruction", "Static"];
 
+
+/**
+ * Utility functions
+ */
+
 function fractionToTiles(f)
 {
 	return getMapSize() * f;
@@ -103,7 +119,7 @@
 	if (numArgs != 1)
 	{
 		var ret = new Array(numArgs);
-		for (var i=0; i < numArgs; i++)
+		for (var i=0; i < numArgs; ++i)
 		{
 			ret[i] = x[i];
 		}
@@ -125,14 +141,16 @@
 	return ar[randInt(ar.length)];
 }
 
-// "Inside-out" implementation of Fisher-Yates shuffle
+/**
+ * "Inside-out" implementation of Fisher-Yates shuffle
+ */
 function shuffleArray(source)
 {
 	if (!source.length)
 		return [];
 
 	var result = [source[0]];
-	for (var i = 1; i < source.length; i++)
+	for (var i = 1; i < source.length; ++i)
 	{
 		var j = randInt(0, i);
 		result[i] = result[j];
@@ -172,12 +190,12 @@
 		var area = g_Map.createArea(centeredPlacer, painter, constraint);
 		if (area !== undefined)
 		{
-			good++;
+			++good;
 			result.push(area);
 		}
 		else
 		{
-			bad++;
+			++bad;
 		}
 	}
 	return result;
@@ -208,12 +226,12 @@
 		var area = g_Map.createArea(centeredPlacer, painter, constraint);
 		if (area !== undefined)
 		{
-			good++;
+			++good;
 			result.push(area);
 		}
 		else
 		{
-			bad++;
+			++bad;
 		}
 	}
 	return result;
@@ -248,11 +266,11 @@
 		var result = createObjectGroup(placer, player, constraint);
 		if (result !== undefined)
 		{
-			good++;
+			++good;
 		}
 		else
 		{
-			bad++;
+			++bad;
 		}
 	}
 	return good;
@@ -282,11 +300,11 @@
 		var result = createObjectGroup(placer, player, constraint);
 		if (result !== undefined)
 		{
-			good++;
+			++good;
 		}
 		else
 		{
-			bad++;
+			++bad;
 		}
 	}
 	return good;
@@ -349,9 +367,9 @@
 	return (g_MapSettings.CircularMap ? true : false);
 }
 
-/////////////////////////////////////////////////////////////////////////////////////////////
-//	Access global map variable
-/////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Access global map variable
+ */
 
 function createTileClass()
 {
@@ -394,15 +412,137 @@
 	return g_MapSettings.PlayerData.length - 1;
 }
 
+/**
+ * Takes nothing, returns an array of strings representing all available civilizations
+ */
+function getCivList()
+{
+	var raw_civData = RMS.GetCivData();
+	var civList = [];
+	for (var i = 0; i < raw_civData.length; ++i)
+		civList.push(JSON.parse(raw_civData[i]).Code);
+	
+	return civList;
+}
+
+/**
+ * Takes nothing, returns an associative array with civ strings as keys containing all unpacked civ data (Templates need to be unpacked with RMS.GetTemplate() if needed)
+ */
+function getFullCivData()
+{
+	var rawCivData = RMS.GetCivData();
+	var unpackedCivData = {};
+	for (var i = 0; i < rawCivData.length; ++i)
+	{
+		var singleCivData = JSON.parse(rawCivData[i]);
+		unpackedCivData[singleCivData.Code] = singleCivData;
+	}
+	
+	return unpackedCivData;
+}
+
+/**
+ * Takes a player number (0-7, so Gaia excluded). Returns this players civ string
+ * ToDo: If the player number is to high an error will occur (and the fallback won't be reached)!
+ */
 function getCivCode(player)
 {
 	if (g_MapSettings.PlayerData[player+1].Civ)
 		return g_MapSettings.PlayerData[player+1].Civ;
 
-	warn("undefined civ specified for player " + (player + 1) + ", falling back to '" + FALLBACK_CIV + "'");
+	warn("Undefined civ specified for player " + (player + 1) + ", falling back to '" + FALLBACK_CIV + "'");
 	return FALLBACK_CIV;
 }
 
+/**
+ * Takes an entity path and a key list to get the templates value
+ */
+function getTemplateValue(entPath, key_list)
+{
+	var subdata = RMS.GetTemplate(entPath);
+	for (var i = 0; i < key_list.length; ++i)
+	{
+		if (!subdata[key_list[i]])
+		{
+			return false
+		}
+		subdata = subdata[key_list[i]];
+	}
+	return subdata;
+}
+
+/**
+ * Returns a list of all templates paths available to the given civ
+ */
+function getTempatePathList(civ)
+{
+	var templatePaths = getFullCivData();
+	if (!templatePaths[civ])
+	{
+		warn("getTempatePathList: Unknown civ '" + civ + "' not in " + Object.keys(templatePaths));
+		return false;
+	}
+	templatePaths = templatePaths[civ];
+	
+	if (!templatePaths[START_ENTITY_KEYS])
+	{
+		warn("getTempatePathList: Civ has no starting entities as defined in START_ENTITY_KEYS (" + START_ENTITY_KEYS + "): " + Object.keys(templatePaths));
+		return false;
+	}
+	templatePaths = templatePaths[START_ENTITY_KEYS];
+	
+	for (var i = 0; i < templatePaths.length; ++i)
+	{
+		if (!templatePaths[i][START_ENTITY_TEMPLATE_KEYS])
+		{
+			warn("getTempatePathList: Starting entity list item has no template as defined in START_ENTITY_TEMPLATE_KEYS (" + START_ENTITY_TEMPLATE_KEYS + "): " + Object.keys(templatePaths));
+			return false;
+		}
+		templatePaths[i] = templatePaths[i][START_ENTITY_TEMPLATE_KEYS];
+	}
+	var foundNew = 1;
+	while (foundNew > 0)
+	{
+		foundNew = 0;
+		var methods = [BUILDER_TEMPLATEPATH_KEYS, PRODUCTION_TEMPLATEPATH_KEYS];
+		for (var m = 0; m < methods.length; ++m)
+		{
+			for (var t = 0; t < templatePaths.length; ++t)
+			{
+				var pathsToCheck = getTemplateValue(templatePaths[t], methods[m]);
+				if (typeof(pathsToCheck) === typeof(""))
+				{
+					pathsToCheck = pathsToCheck.split(/\s+/);
+					for (var c = 0; c < pathsToCheck.length; ++c)
+					{
+						var actualPath = pathsToCheck[c].replace(CIV_PLACEHOLDER_STRING, civ);
+						if (templatePaths.indexOf(actualPath) == -1 && RMS.TemplateExists(actualPath))
+						{
+							templatePaths.push(actualPath);
+							++foundNew;
+						}
+					}
+				}
+			}
+		}
+	}
+	return templatePaths;
+}
+
+/**
+ * Takes a list of entity path strings and returns a list with only those remaining that have the specified keys
+ */
+function filterByKeys(entPaths, keys)
+{
+	let filteredEntPaths = [];
+	for (let i = 0; i < entPaths.length; ++i)
+	{
+		if (getTemplateValue(entPaths[i], keys))
+			filteredEntPaths.push(entPaths[i]);
+	}
+	return filteredEntPaths;
+}
+
 function areAllies(player1, player2)
 {
 	if ((g_MapSettings.PlayerData[player1+1].Team === undefined) || (g_MapSettings.PlayerData[player2+1].Team === undefined) || (g_MapSettings.PlayerData[player2+1].Team == -1) || (g_MapSettings.PlayerData[player1+1].Team == -1))
@@ -434,19 +574,17 @@
 
 	var result = new Array(0);
 	var team = new Array(5);
-	for (var q = 0; q < 5; q++)
+	for (var q = 0; q < 5; ++q)
 	{
 		team[q] = new Array(1);
 	}
 
-	for (var i = -1; i < 4; i++)
+	for (var i = -1; i < 4; ++i)
 	{
-		for (var j = 0; j < source.length; j++)
+		for (var j = 0; j < source.length; ++j)
 		{
 			if (getPlayerTeam(j) == i)
-			{
 				team[i+1].unshift(j+1);
-			}
 		}
 		team[i+1].pop();
 		result=result.concat(shuffleArray(team[i+1]))
@@ -461,7 +599,7 @@
 
 	var prime = new Array(source.length);
 
-	for (var i = 0; i < round(source.length/2); i++)
+	for (var i = 0; i < round(source.length/2); ++i)
 	{
 		prime[2*i]=source[i];
 		prime[2*i+1]=source[source.length-1-i];
@@ -492,70 +630,76 @@
 	g_Map.setHeight(x, z, height);
 }
 
-/////////////////////////////////////////////////////////////////////////////////////////////
-//	Utility functions for classes
-/////////////////////////////////////////////////////////////////////////////////////////////
 
+/**
+ *	Utility functions for classes
+ */
 
-// Add point to given class by id
+/**
+ * Add point to given class by id
+ */
 function addToClass(x, z, id)
 {
 	var tileClass = getTileClass(id);
 	
 	if (tileClass !== null)
-	{
 		tileClass.add(x, z);
-	}
 }
 
-// Remove point from the given class by id
+/**
+ * Remove point from the given class by id
+ */
 function removeFromClass(x, z, id)
 {
 	var tileClass = getTileClass(id);
 	
 	if (tileClass !== null)
-	{
 		tileClass.remove(x, z);
-	}
 }
 
-// Create a painter for the given class
+/**
+ * Create a painter for the given class
+ */
 function paintClass(id)
 {
 	return new TileClassPainter(getTileClass(id));
 }
 
-// Create a painter for the given class
+/**
+ * Create a painter for the given class
+ */
 function unPaintClass(id)
 {
 	return new TileClassUnPainter(getTileClass(id));
 }
 
-// Create an avoid constraint for the given classes by the given distances
+/**
+ * Create an avoid constraint for the given classes by the given distances
+ */
 function avoidClasses(/*class1, dist1, class2, dist2, etc*/)
 {
 	var ar = new Array(arguments.length/2);
-	for (var i = 0; i < arguments.length/2; i++)
+	for (var i = 0; i < arguments.length/2; ++i)
 	{
 		ar[i] = new AvoidTileClassConstraint(arguments[2*i], arguments[2*i+1]);
 	}
 	
 	// Return single constraint
 	if (ar.length == 1)
-	{
 		return ar[0];
-	}
 	else
 	{
 		return new AndConstraint(ar);
 	}
 }
 
-// Create a stay constraint for the given classes by the given distances
+/**
+ * Create a stay constraint for the given classes by the given distances
+ */
 function stayClasses(/*class1, dist1, class2, dist2, etc*/)
 {
 	var ar = new Array(arguments.length/2);
-	for (var i = 0; i < arguments.length/2; i++)
+	for (var i = 0; i < arguments.length/2; ++i)
 	{
 		ar[i] = new StayInTileClassConstraint(arguments[2*i], arguments[2*i+1]);
 	}
@@ -571,11 +715,13 @@
 	}
 }
 
-// Create a border constraint for the given classes by the given distances
+/**
+ * Create a border constraint for the given classes by the given distances
+ */
 function borderClasses(/*class1, idist1, odist1, class2, idist2, odist2, etc*/)
 {
 	var ar = new Array(arguments.length/3);
-	for (var i = 0; i < arguments.length/3; i++)
+	for (var i = 0; i < arguments.length/3; ++i)
 	{
 		ar[i] = new BorderTileClassConstraint(arguments[3*i], arguments[3*i+1], arguments[3*i+2]);
 	}
@@ -591,7 +737,9 @@
 	}
 }
 
-// Checks if the given tile is in class "id"
+/**
+ * Checks if the given tile is in class "id"
+ */
 function checkIfInClass(x, z, id)
 {
 	var tileClass = getTileClass(id);
@@ -612,20 +760,25 @@
 	}
 }
 
-
-// Returns the distance between 2 points
+/**
+ * Returns the distance between 2 points
+ */
 function getDistance(x1, z1, x2, z2)
 {
 	return Math.pow(Math.pow(x1 - x2, 2) + Math.pow(z1 - z2, 2), 1/2);
 }
 
-// Returns the angle of the vector between point 1 and point 2.  The angle is anticlockwise from the positive x axis.
+/**
+ * Returns the angle of the vector between point 1 and point 2.  The angle is anticlockwise from the positive x axis.
+ */
 function getAngle(x1, z1, x2, z2)
 {
 	return Math.atan2(z2 - z1, x2 - x1);
 }
 
-// Returns the gradient of the line between point 1 and 2 in the form dz/dx
+/**
+ * Returns the gradient of the line between point 1 and 2 in the form dz/dx
+ */
 function getGradient(x1, z1, x2, z2)
 {
 	if (x1 == x2 && z1 == z2)
@@ -642,4 +795,3 @@
 {
 	return g_Map.getTexture(x, y);
 }
-
Index: binaries/data/mods/public/maps/random/rmgen/misc.js
===================================================================
--- binaries/data/mods/public/maps/random/rmgen/misc.js	(revision 17723)
+++ binaries/data/mods/public/maps/random/rmgen/misc.js	(working copy)
@@ -1,28 +1,26 @@
-/////////////////////////////////////////////////////////////////////////////////////////
-//	passageMaker
-//
-//	Function for creating shallow water between two given points by changing the heiight of all tiles in
-//	the path with height less than or equal to "maxheight" to "height"
-//
-//	x1,z1: 	Starting point of path
-//	x2,z2: 	Ending point of path
-//	width: 	Width of the shallow
-//	maxheight:		Maximum height that it changes
-//	height:		Height of the shallow
-//	smooth:		smooth elevation in borders
-//	tileclass:		(Optianal) - Adds those tiles to the class given
-//	terrain:		(Optional) - Changes the texture of the elevated land
-//
-/////////////////////////////////////////////////////////////////////////////////////////
-
+/**
+ *	passageMaker
+ *
+ *	Function for creating shallow water between two given points by changing the heiight of all tiles in
+ *	the path with height less than or equal to "maxheight" to "height"
+ *
+ *	x1,z1: 	Starting point of path
+ *	x2,z2: 	Ending point of path
+ *	width: 	Width of the shallow
+ *	maxheight:		Maximum height that it changes
+ *	height:		Height of the shallow
+ *	smooth:		smooth elevation in borders
+ *	tileclass:		(Optianal) - Adds those tiles to the class given
+ *	terrain:		(Optional) - Changes the texture of the elevated land
+ */
 function passageMaker(x1, z1, x2, z2, width, maxheight, height, smooth, tileclass, terrain, riverheight)
 {
 	var tchm = TILE_CENTERED_HEIGHT_MAP;
 	TILE_CENTERED_HEIGHT_MAP = true;
 	var mapSize = g_Map.size;
-	for (var ix = 0; ix < mapSize; ix++)
+	for (var ix = 0; ix < mapSize; ++ix)
 	{
-		for (var iz = 0; iz < mapSize; iz++)
+		for (var iz = 0; iz < mapSize; ++iz)
 		{
 			var a = z1-z2;
 			var b = x2-x1;
@@ -73,18 +71,16 @@
 	TILE_CENTERED_HEIGHT_MAP = tchm;
 }
 
-//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//rndRiver is a fuction that creates random values useful for making a jagged river.
-//
-//it works the same as sin or cos function. the only difference is that it's period is 1 instead of 2*pi
-//it needs the "seed" parameter to use it to make random curves that don't get broken.
-//seed must be created using randFloat(). or else it won't work
-//
-//	f:	Input: Same as angle in a sine function
-//	seed:	Random Seed: Best to implement is to use randFloat()
-//
-//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
+/**
+ *rndRiver is a fuction that creates random values useful for making a jagged river.
+ *
+ *it works the same as sin or cos function. the only difference is that it's period is 1 instead of 2*pi
+ *it needs the "seed" parameter to use it to make random curves that don't get broken.
+ *seed must be created using randFloat(). or else it won't work
+ *
+ *	f:	Input: Same as angle in a sine function
+ *	seed:	Random Seed: Best to implement is to use randFloat()
+ */
 function rndRiver(f, seed)
 {
 	var rndRq = seed;
@@ -92,7 +88,7 @@
 	var rndRe = 0;
 	var rndRr = f-floor(f);
 	var rndRa = 0;
-	for (var rndRx=0; rndRx<=floor(f); rndRx++)
+	for (var rndRx=0; rndRx<=floor(f); ++rndRx)
 	{
 		rndRw = 10*(rndRw-floor(rndRw));
 	}
@@ -129,16 +125,15 @@
 }
 
 
-/////////////////////////////////////////////////////////////////////////////////////////
-// createStartingPlayerEntities
-//
-//	Creates the starting player entities
-//	fx&fz: position of player base
-//	playerid: id of player
-//	civEntities: use getStartingEntities(id-1) fo this one
-//	BUILDING_ANGlE: angle of main base building
-//
-///////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * createStartingPlayerEntities
+ *
+ *	Creates the starting player entities
+ *	fx&fz: position of player base
+ *	playerid: id of player
+ *	civEntities: use getStartingEntities(id-1) fo this one
+ *	BUILDING_ANGlE: angle of main base building
+ */
 function createStartingPlayerEntities(fx, fz, playerid, civEntities, BUILDING_ANGlE)
 {
 	var uDist = 6;
@@ -148,7 +143,7 @@
 	{
 		var uAngle = BUILDING_ANGlE - PI * (2-j) / 2;
 		var count = (civEntities[j].Count !== undefined ? civEntities[j].Count : 1);
-		for (var numberofentities = 0; numberofentities < count; numberofentities++)
+		for (var numberofentities = 0; numberofentities < count; ++numberofentities)
 		{
 			var ux = fx + uDist * cos(uAngle) + numberofentities * uSpace * cos(uAngle + PI/2) - (0.75 * uSpace * floor(count / 2) * cos(uAngle + PI/2));
 			var uz = fz + uDist * sin(uAngle) + numberofentities * uSpace * sin(uAngle + PI/2) - (0.75 * uSpace * floor(count / 2) * sin(uAngle + PI/2));
@@ -157,17 +152,16 @@
 	}
 }
 
-//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// placeCivDefaultEntities
-//
-//	Creates the default starting player entities depending on the players civ
-//	fx&fy: position of player base
-//	playerid: id of player
-//	angle: angle of main base building, optional, default is BUILDING_ANGlE
-//	kwargs: Takes some optional keyword arguments to tweek things
-//		'iberWall': may be false, 'walls' (default) or 'towers'. Determines the defensive structures Iberians get as civ bonus
-//
-//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * placeCivDefaultEntities
+ *
+ *	Creates the default starting player entities depending on the players civ
+ *	fx&fy: position of player base
+ *	playerid: id of player
+ *	angle: angle of main base building, optional, default is BUILDING_ANGlE
+ *	kwargs: Optional. Takes an associative array with keyword arguments to tweak things:
+ *		Known keys: 'iberWall': may be false, 'walls' (default) or 'towers'. Determines the defensive structures Iberians get as civ bonus
+ */
 function placeCivDefaultEntities(fx, fz, playerid, angle, kwargs)
 {
 	// Unpack kwargs
@@ -187,7 +181,7 @@
 	{
 		var uAngle = angle - PI * (2-j) / 2;
 		var count = (civEntities[j].Count !== undefined ? civEntities[j].Count : 1);
-		for (var numberofentities = 0; numberofentities < count; numberofentities++)
+		for (var numberofentities = 0; numberofentities < count; ++numberofentities)
 		{
 			var ux = fx + uDist * cos(uAngle) + numberofentities * uSpace * cos(uAngle + PI/2) - (0.75 * uSpace * floor(count / 2) * cos(uAngle + PI/2));
 			var uz = fz + uDist * sin(uAngle) + numberofentities * uSpace * sin(uAngle + PI/2) - (0.75 * uSpace * floor(count / 2) * sin(uAngle + PI/2));
@@ -205,25 +199,24 @@
 }
 
 
-/////////////////////////////////////////////////////////////////////////////////////////
-// paintTerrainBasedOnHeight
-//
-//	paints the tiles which have a height between minheight and maxheight with the given terrain
-//	minheight: minimum height of the tile
-//	maxheight: maximum height of the tile
-//	mode: accepts 4 values. 0 means the it will select tiles with height more than minheight and less than maxheight.
-//  1 means it selects tiles with height more than or equal to minheight and less than max height. 2 means more than
-//  minheight and less than or equal to maxheight. 3 means more than or equal to minheight and less than or equal to maxheight
-//	terrain: intended terrain texture
-//
-///////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * paintTerrainBasedOnHeight
+ *
+ *	paints the tiles which have a height between minheight and maxheight with the given terrain
+ *	minheight: minimum height of the tile
+ *	maxheight: maximum height of the tile
+ *	mode: accepts 4 values. 0 means the it will select tiles with height more than minheight and less than maxheight.
+ *  1 means it selects tiles with height more than or equal to minheight and less than max height. 2 means more than
+ *  minheight and less than or equal to maxheight. 3 means more than or equal to minheight and less than or equal to maxheight
+ *	terrain: intended terrain texture
+ */
 
 function paintTerrainBasedOnHeight(minheight, maxheight, mode, terrain)
 {
 	var mSize = g_Map.size;
-	for (var qx = 0; qx < mSize; qx++)
+	for (var qx = 0; qx < mSize; ++qx)
 	{
-		for (var qz = 0; qz < mSize; qz++)
+		for (var qz = 0; qz < mSize; ++qz)
 		{
 			if (mode == 0)
 			{
@@ -257,25 +250,23 @@
 	}
 }
 
-/////////////////////////////////////////////////////////////////////////////////////////
-// paintTileClassBasedOnHeight and unPaintTileClassBasedOnHeight
-//
-//	paints or unpaints the tiles which have a height between minheight and maxheight with the given tile class
-//	minheight: minimum height of the tile
-//	maxheight: maximum height of the tile
-//	mode: accepts 4 values. 0 means the it will select tiles with height more than minheight and less than maxheight.
-//  1 means it selects tiles with height more than or equal to minheight and less than max height. 2 means more than
-//  minheight and less than or equal to maxheight. 3 means more than or equal to minheight and less than or equal to maxheight
-//	tileclass: intended tile class
-//
-///////////////////////////////////////////////////////////////////////////////////////////
-
+/**
+ * paintTileClassBasedOnHeight and unPaintTileClassBasedOnHeight
+ *
+ *	paints or unpaints the tiles which have a height between minheight and maxheight with the given tile class
+ *	minheight: minimum height of the tile
+ *	maxheight: maximum height of the tile
+ *	mode: accepts 4 values. 0 means the it will select tiles with height more than minheight and less than maxheight.
+ *  1 means it selects tiles with height more than or equal to minheight and less than max height. 2 means more than
+ *  minheight and less than or equal to maxheight. 3 means more than or equal to minheight and less than or equal to maxheight
+ *	tileclass: intended tile class
+ */
 function paintTileClassBasedOnHeight(minheight, maxheight, mode, tileclass)
 {
 	var mSize = g_Map.size;
-	for (var qx = 0; qx < mSize; qx++)
+	for (var qx = 0; qx < mSize; ++qx)
 	{
-		for (var qz = 0; qz < mSize; qz++)
+		for (var qz = 0; qz < mSize; ++qz)
 		{
 			if (mode == 0)
 			{
@@ -313,9 +304,9 @@
 function unPaintTileClassBasedOnHeight(minheight, maxheight, mode, tileclass)
 {
 	var mSize = g_Map.size;
-	for (var qx = 0; qx < mSize; qx++)
+	for (var qx = 0; qx < mSize; ++qx)
 	{
-		for (var qz = 0; qz < mSize; qz++)
+		for (var qz = 0; qz < mSize; ++qz)
 		{
 			if (mode == 0)
 			{
@@ -349,19 +340,17 @@
 	}
 }
 
-/////////////////////////////////////////////////////////////////////////////////////////
-// getTIPIADBON
-//
-//	"get The Intended Point In A Direction Based On Height"
-//	gets the N'th point with a specific height in a line and returns it as a [x, y] array
-//	startPoint: [x, y] array defining the start point
-//	endPoint: [x, y] array defining the ending point
-//	heightRange: [min, max] array defining the range which the height of the intended point can be. includes both "min" and "max"
-//  step: how much tile units per turn should the search go. more value means faster but less accurate 
-//  n: how many points to skip before ending the search. skips """n-1 points""".
-//
-///////////////////////////////////////////////////////////////////////////////////////////
-
+/**
+ * getTIPIADBON
+ *
+ *	"get The Intended Point In A Direction Based On Height"
+ *	gets the N'th point with a specific height in a line and returns it as a [x, y] array
+ *	startPoint: [x, y] array defining the start point
+ *	endPoint: [x, y] array defining the ending point
+ *	heightRange: [min, max] array defining the range which the height of the intended point can be. includes both "min" and "max"
+ *  step: how much tile units per turn should the search go. more value means faster but less accurate 
+ *  n: how many points to skip before ending the search. skips """n-1 points""".
+ */
 function getTIPIADBON(startPoint, endPoint, heightRange, step, n)
 {
 	var stepX = step*(endPoint[0]-startPoint[0])/(sqrt((endPoint[0]-startPoint[0])*(endPoint[0]-startPoint[0]) + step*(endPoint[1]-startPoint[1])*(endPoint[1]-startPoint[1])));
@@ -394,16 +383,14 @@
 	return undefined;
 }
 
-/////////////////////////////////////////////////////////////////////////////////////////
-// doIntersect
-//
-//	determines if two lines with the width "width" intersect or collide with each other
-//	x1, y1, x2, y2: determine the position of the first line
-//	x3, y3, x4, y4: determine the position of the second line
-//	width: determines the width of the lines
-//
-///////////////////////////////////////////////////////////////////////////////////////////
-
+/**
+ * doIntersect
+ *
+ *	determines if two lines with the width "width" intersect or collide with each other
+ *	x1, y1, x2, y2: determine the position of the first line
+ *	x3, y3, x4, y4: determine the position of the second line
+ *	width: determines the width of the lines
+ */
 function checkIfIntersect (x1, y1, x2, y2, x3, y3, x4, y4, width)
 {
 	if (x1 == x2)
@@ -445,15 +432,13 @@
 	return false;
 }
 
-/////////////////////////////////////////////////////////////////////////////////////////
-// distanceOfPointFromLine
-//
-//	returns the distance of a point from a line
-//	x1, y1, x2, y2: determine the position of the line
-//	x3, y3: determine the position of the point
-//
-///////////////////////////////////////////////////////////////////////////////////////////
-
+/**
+ * distanceOfPointFromLine
+ *
+ *	returns the distance of a point from a line
+ *	x1, y1, x2, y2: determine the position of the line
+ *	x3, y3: determine the position of the point
+ */
 function distanceOfPointFromLine (x1, y1, x2, y2, x3, y3)
 {
 	if (x1 == x2)
@@ -473,20 +458,18 @@
 	}
 }
 
-/////////////////////////////////////////////////////////////////////////////////////////
-// createRamp
-//
-//	creates a ramp from point (x1, y1) to (x2, y2).
-//	x1, y1, x2, y2: determine the position of the start and end of the ramp
-//	minHeight, maxHeight: determine the height levels of the start and end point
-//	width: determines the width of the ramp
-//	smoothLevel: determines the smooth level around the edges of the ramp
-//	mainTerrain: (Optional) determines the terrain texture for the ramp
-//	edgeTerrain: (Optional) determines the terrain texture for the edges
-//	tileclass: (Optional) adds the ramp to this tile class
-//
-///////////////////////////////////////////////////////////////////////////////////////////
-
+/**
+ * createRamp
+ *
+ *	creates a ramp from point (x1, y1) to (x2, y2).
+ *	x1, y1, x2, y2: determine the position of the start and end of the ramp
+ *	minHeight, maxHeight: determine the height levels of the start and end point
+ *	width: determines the width of the ramp
+ *	smoothLevel: determines the smooth level around the edges of the ramp
+ *	mainTerrain: (Optional) determines the terrain texture for the ramp
+ *	edgeTerrain: (Optional) determines the terrain texture for the edges
+ *	tileclass: (Optional) adds the ramp to this tile class
+ */
 function createRamp (x1, y1, x2, y2, minHeight, maxHeight, width, smoothLevel, mainTerrain, edgeTerrain, tileclass)
 {
 	var halfWidth = width / 2;
@@ -540,12 +523,12 @@
 	}
 }
 
-/////////////////////////////////////////////////////////////////////////////////////////
-// createMountain
-//
-//	creates a mountain using a tecnique very similar to chain placer.
-//
-///////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * createMountain
+ *
+ *	creates a mountain using a tecnique very similar to chain placer.
+ *
+ */
 
 function createMountain(maxHeight, minRadius, maxRadius, numCircles, constraint, x, z, terrain, tileclass, fcc, q)
 {
@@ -617,7 +600,7 @@
 		
 		for (var ix = sx; ix <= lx; ++ix)
 		{
-			for (var iz = sz; iz <= lz; ++ iz)
+			for (var iz = sz; iz <= lz; ++iz)
 			{
 				dx = ix - cx;
 				dz = iz - cz;
@@ -666,7 +649,7 @@
 		
 		for (var ix = sx; ix <= lx; ++ix)
 		{
-			for (var iz = sz; iz <= lz; ++ iz)
+			for (var iz = sz; iz <= lz; ++iz)
 			{
 				if (fcc)
 					if ((x - ix) > fcc || (ix - x) > fcc || (z - iz) > fcc || (iz - z) > fcc)
@@ -737,7 +720,7 @@
 		
 		for (var ix = sx; ix <= lx; ++ix)
 		{
-			for (var iz = sz; iz <= lz; ++ iz)
+			for (var iz = sz; iz <= lz; ++iz)
 			{
 				dx = ix - cx;
 				dz = iz - cz;
Index: binaries/data/mods/public/maps/random/schwarzwald.js
===================================================================
--- binaries/data/mods/public/maps/random/schwarzwald.js	(revision 17723)
+++ binaries/data/mods/public/maps/random/schwarzwald.js	(working copy)
@@ -1,43 +1,50 @@
-// Created by Niek ten Brinke (aka niektb)
-// Based on FeXoR's Daimond Square Algorithm for heightmap generation and several official random maps
+/**
+ * Created by Niek ten Brinke (aka niektb)
+ * Based on FeXoR's Daimond Square Algorithm for heightmap generation and several official random maps
+ */
 
 'use strict';
 
 RMS.LoadLibrary('rmgen');
 
-// initialize map
+/**
+ * initialize map
+ */
 
 log('Initializing map...');
 
 InitMap();
 
 
-////////////////
-//
-//  Initializing
-//
-////////////////
+/**
+ *  Initializing
+ */
 
-//sky
+/**
+ *sky
+ */
 setSkySet("fog");
 setFogFactor(0.35);
 setFogThickness(0.19);
-
-// water
+/**
+ * water
+ */
 setWaterColor(0.501961, 0.501961, 0.501961);
 setWaterTint(0.25098, 0.501961, 0.501961);
 setWaterWaviness(0.5);
 setWaterType("clap");
 setWaterMurkiness(0.75);
-
-// post processing
+/**
+ * post processing
+ */
 setPPSaturation(0.37);
 setPPContrast(0.4);
 setPPBrightness(0.4);
 setPPEffect("hdr");
 setPPBloom(0.4);
-
-// Setup tile classes
+/**
+ * Setup tile classes
+ */
 var clPlayer = createTileClass();
 var clPath = createTileClass();
 var clHill = createTileClass();
@@ -47,8 +54,9 @@
 var clFood = createTileClass();
 var clBaseResource = createTileClass();
 var clOpen = createTileClass();
-
-// Setup Templates
+/**
+ * Setup Templates
+ */
 var templateStone = 'gaia/geology_stone_alpine_a';
 var templateStoneMine = 'gaia/geology_stonemine_alpine_quarry';
 var templateMetal = 'actor|geology/stone_granite_med.xml';
@@ -64,8 +72,9 @@
 var aReeds = 'actor|props/flora/reeds_pond_lush_b.xml';
 var oFish = "gaia/fauna_fish";
 
-
-// Setup terrain
+/**
+ * Setup terrain
+ */
 var terrainWood = ['alpine_forrestfloor|gaia/flora_tree_oak', 'alpine_forrestfloor|gaia/flora_tree_pine']; 
 var terrainWoodBorder = ['new_alpine_grass_mossy|gaia/flora_tree_oak', 'alpine_forrestfloor|gaia/flora_tree_pine',
 	'temp_grass_long|gaia/flora_bush_temperate', 'temp_grass_clovers|gaia/flora_bush_berry', 'temp_grass_clovers_2|gaia/flora_bush_grapes',
@@ -108,14 +117,18 @@
 
 const BUILDING_ANGlE = -PI/4;
 
-// Setup map 
+/**
+ * Setup map 
+ */
 var mapSize = getMapSize();
 var mapRadius = mapSize/2;
 var playableMapRadius = mapRadius - 5;
 var mapCenterX = mapRadius;
 var mapCenterZ = mapRadius;
 
-// Setup players and bases
+/**
+ * Setup players and bases
+ */
 var numPlayers = getNumPlayers();
 var baseRadius = 15;
 var minPlayerRadius = min(mapRadius-1.5*baseRadius, 5*mapRadius/8);
@@ -128,28 +141,31 @@
 var playerAngleAddAvrg = 2*PI / numPlayers;
 var playerAngleMaxOff = playerAngleAddAvrg/4;
 
-// Setup paths
+/**
+ * Setup paths
+ */
 var pathSucsessRadius = baseRadius/2;
 var pathAngleOff = PI/2;
-var pathWidth = 10; // This is not really the path's thickness in tiles but the number of tiles in the clumbs of the path
+var pathWidth = 10; // This is not really the path's thickness in tiles but the number of tiles in the clumps of the path
 
-// Setup additional resources
+/**
+ * Setup additional resources
+ */
 var resourceRadius = 2*mapRadius/3; // 3*mapRadius/8;
 //var resourcePerPlayer = [templateStone, templateMetalMine];
 
-// Setup woods
-// For large maps there are memory errors with too many trees.  A density of 256*192/mapArea works with 0 players.
-// Around each player there is an area without trees so with more players the max density can increase a bit.
+/**
+ * Setup woods
+ * For large maps there are memory errors with too many trees.  A density of 256*192/mapArea works with 0 players.
+ * Around each player there is an area without trees so with more players the max density can increase a bit.
+ */
 var maxTreeDensity = min(256 * (192 + 8 * numPlayers) / (mapSize * mapSize), 1); // Has to be tweeked but works ok 
 var bushChance = 1/3; // 1 means 50% chance in deepest wood, 0.5 means 25% chance in deepest wood
 
 
-////////////////
-//
-//  Some general functions
-//
-////////////////
-
+/**
+ * Some general functions
+ */
 function HeightPlacer(lowerBound, upperBound) {
     this.lowerBound = lowerBound;
     this.upperBound = upperBound;
@@ -159,8 +175,8 @@
 	constraint = (constraint || new NullConstraint());
 	
     var ret = [];
-    for (var x = 0; x < g_Map.size; x++) {
-        for (var y = 0; y < g_Map.size; y++) {
+    for (var x = 0; x < g_Map.size; ++x) {
+        for (var y = 0; y < g_Map.size; ++y) {
             if (g_Map.height[x][y] >= this.lowerBound && g_Map.height[x][y] <= this.upperBound && constraint.allows(x, y)) {
                 ret.push(new PointXZ(x, y));
             }
@@ -169,17 +185,17 @@
     return ret;
 };
 
-/*
-Takes an array of 2D points (arrays of length 2)
-Returns the order to go through the points for the shortest closed path (array of indices)
-*/
+/**
+ * Takes an array of 2D points (arrays of length 2)
+ * Returns the order to go through the points for the shortest closed path (array of indices)
+ */
 function getOrderOfPointsForShortestClosePath(points)
 {
 	var order = [];
 	var distances = [];
 	if (points.length <= 3)
 	{
-		for (var i = 0; i < points.length; i++)
+		for (var i = 0; i < points.length; ++i)
 			order.push(i);
 		
 		return order;
@@ -187,7 +203,7 @@
 	
 	// Just add the first 3 points
 	var pointsToAdd = deepcopy(points);
-	for (var i = 0; i < min(points.length, 3); i++)
+	for (var i = 0; i < min(points.length, 3); i)
 	{
 		order.push(i);
 		pointsToAdd.shift(i);
@@ -198,13 +214,13 @@
 	
 	// Add remaining points so the path lengthens the least
 	var numPointsToAdd = pointsToAdd.length;
-	for (var i = 0; i < numPointsToAdd; i++)
+	for (var i = 0; i < numPointsToAdd; ++i)
 	{
 		var indexToAddTo = undefined;
 		var minEnlengthen = Infinity;
 		var minDist1 = 0;
 		var minDist2 = 0;
-		for (var k = 0; k < order.length; k++)
+		for (var k = 0; k < order.length; ++k)
 		{
 			var dist1 = getDistance(pointsToAdd[0][0], pointsToAdd[0][1], points[order[k]][0], points[order[k]][1]);
 			var dist2 = getDistance(pointsToAdd[0][0], pointsToAdd[0][1], points[order[(k + 1) % order.length]][0], points[order[(k + 1) % order.length]][1]);
@@ -226,25 +242,21 @@
 }
 
 
-////////////////
-//
-//  Heightmap functionality
-//
-////////////////
+/**
+ *  Heightmap functionality
+ */
 
-// Some heightmap constants
-const MIN_HEIGHT = - SEA_LEVEL; // -20
-const MAX_HEIGHT = 0xFFFF/HEIGHT_UNITS_PER_METRE - SEA_LEVEL; // A bit smaller than 90
-
-// Get the diferrence between minimum and maxumum height
+/**
+ * Get the diferrence between minimum and maxumum height
+ */
 function getMinAndMaxHeight(reliefmap)
 {
 	var height = {};
 	height.min = Infinity;
 	height.max = - Infinity;
-	for (var x = 0; x < reliefmap.length; x++)
+	for (var x = 0; x < reliefmap.length; ++x)
 	{
-		for (var y = 0; y < reliefmap[x].length; y++)
+		for (var y = 0; y < reliefmap[x].length; ++y)
 		{
 			if (reliefmap[x][y] < height.min)
 				height.min = reliefmap[x][y];
@@ -264,22 +276,22 @@
 	var oldHeightRange = getMinAndMaxHeight(heightmap);
 	var max_x = heightmap.length;
 	var max_y = heightmap[0].length;
-	for (var x = 0; x < max_x; x++)
-		for (var y = 0; y < max_y; y++)
+	for (var x = 0; x < max_x; ++x)
+		for (var y = 0; y < max_y; ++y)
 			heightmap[x][y] = minHeight + (heightmap[x][y] - oldHeightRange.min) / (oldHeightRange.max - oldHeightRange.min) * (maxHeight - minHeight);
 }
 
-/*
-getStartLocationsByHeightmap
-Takes
-	hightRange		An associative array with keys 'min' and 'max' each containing a float (the height range start locations are allowed)
-	heightmap		Optional, default is g_Map.height, an array of (map width) arrays of (map depth) floats
-	maxTries		Optional, default is 1000, an integer, how often random player distributions are rolled to be compared
-	minDistToBorder	Optional, default is 20, an integer, how far start locations have to be 
-	numberOfPlayers	Optional, default is getNumPlayers, an integer, how many start locations should be placed
-Returns
-	An array of 2D points (arrays of length 2)
-*/
+/**
+ * getStartLocationsByHeightmap
+ * Takes
+ *	hightRange		An associative array with keys 'min' and 'max' each containing a float (the height range start locations are allowed)
+ *	heightmap		Optional, default is g_Map.height, an array of (map width) arrays of (map depth) floats
+ *	maxTries		Optional, default is 1000, an integer, how often random player distributions are rolled to be compared
+ *	minDistToBorder	Optional, default is 20, an integer, how far start locations have to be 
+ *	numberOfPlayers	Optional, default is getNumPlayers, an integer, how many start locations should be placed
+ * Returns
+ *	An array of 2D points (arrays of length 2)
+ */
 function getStartLocationsByHeightmap(hightRange, maxTries, minDistToBorder, numberOfPlayers, heightmap)
 {
 	maxTries = (maxTries || 1000);
@@ -288,21 +300,21 @@
 	heightmap = (heightmap || g_Map.height);
 	
 	var validStartLocTiles = [];
-	for (var x = minDistToBorder; x < heightmap.length - minDistToBorder; x++)
-		for (var y = minDistToBorder; y < heightmap[0].length - minDistToBorder; y++)
+	for (var x = minDistToBorder; x < heightmap.length - minDistToBorder; ++x)
+		for (var y = minDistToBorder; y < heightmap[0].length - minDistToBorder; ++y)
 			if (heightmap[x][y] > hightRange.min && heightmap[x][y] < hightRange.max) // Has the right hight
 				validStartLocTiles.push([x, y]);
 	
 	var maxMinDist = 0;
-	for (var tries = 0; tries < maxTries; tries++)
+	for (var tries = 0; tries < maxTries; ++tries)
 	{
 		var startLoc = [];
 		var minDist = heightmap.length;
-		for (var p = 0; p < numberOfPlayers; p++)
+		for (var p = 0; p < numberOfPlayers; ++p)
 			startLoc.push(validStartLocTiles[randInt(validStartLocTiles.length)]);
-		for (var p1 = 0; p1 < numberOfPlayers - 1; p1++)
+		for (var p1 = 0; p1 < numberOfPlayers - 1; ++p1)
 		{
-			for (var p2 = p1 + 1; p2 < numberOfPlayers; p2++)
+			for (var p2 = p1 + 1; p2 < numberOfPlayers; ++p2)
 			{
 				var dist = getDistance(startLoc[p1][0], startLoc[p1][1], startLoc[p2][0], startLoc[p2][1]);
 				if (dist < minDist)
@@ -319,18 +331,18 @@
 	return finalStartLoc;
 }
 
-/*
-derivateEntitiesByHeight
-Takes
-	hightRange		An associative array with keys 'min' and 'max' each containing a float (the height range start locations are allowed)
-	startLoc		An array of 2D points (arrays of length 2)
-	heightmap		Optional, default is g_Map.height, an array of (map width) arrays of (map depth) floats
-	entityList		Array of entities/actors (strings to be placed with placeObject())
-	maxTries		Optional, default is 1000, an integer, how often random player distributions are rolled to be compared
-	minDistance		Optional, default is 30, an integer, how far start locations have to be away from start locations and the map border
-Returns
-	An array of 2D points (arrays of length 2)
-*/
+/**
+ *derivateEntitiesByHeight
+ *Takes
+ *	hightRange		An associative array with keys 'min' and 'max' each containing a float (the height range start locations are allowed)
+ *	startLoc		An array of 2D points (arrays of length 2)
+ *	heightmap		Optional, default is g_Map.height, an array of (map width) arrays of (map depth) floats
+ *	entityList		Array of entities/actors (strings to be placed with placeObject())
+ *	maxTries		Optional, default is 1000, an integer, how often random player distributions are rolled to be compared
+ *	minDistance		Optional, default is 30, an integer, how far start locations have to be away from start locations and the map border
+ *Returns
+ *	An array of 2D points (arrays of length 2)
+ */
 function derivateEntitiesByHeight(hightRange, startLoc, entityList, maxTries, minDistance, heightmap)
 {
 	entityList = (entityList || [templateMetalMine, templateStoneMine]);
@@ -340,19 +352,19 @@
 	
 	var placements = deepcopy(startLoc);
 	var validTiles = [];
-	for (var x = minDistance; x < heightmap.length - minDistance; x++)
-		for (var y = minDistance; y < heightmap[0].length - minDistance; y++)
+	for (var x = minDistance; x < heightmap.length - minDistance; ++x)
+		for (var y = minDistance; y < heightmap[0].length - minDistance; ++y)
 			if (heightmap[x][y] > hightRange.min && heightmap[x][y] < hightRange.max) // Has the right hight
 				validTiles.push([x, y]);
 	
 	if (!validTiles.length)
 		return;
 	
-	for (var tries = 0; tries < maxTries; tries++)
+	for (var tries = 0; tries < maxTries; ++tries)
 	{
 		var tile = validTiles[randInt(validTiles.length)];
 		var isValid = true;
-		for (var p = 0; p < placements.length; p++)
+		for (var p = 0; p < placements.length; ++p)
 		{
 			if (getDistance(placements[p][0], placements[p][1], tile[0], tile[1]) < minDistance)
 			{
@@ -370,11 +382,9 @@
 }
 
 
-////////////////
-//
-//  Base terrain generation functionality
-//
-////////////////
+/**
+ *  Base terrain generation functionality
+ */
 
 function setBaseTerrainDiamondSquare(minHeight, maxHeight, smoothness, initialHeightmap, heightmap)
 {
@@ -395,10 +405,10 @@
 		var newHeightmap = [];
 		var oldWidth = initialHeightmap.length;
 		// Square
-		for (var x = 0; x < 2 * oldWidth - 1; x++)
+		for (var x = 0; x < 2 * oldWidth - 1; ++x)
 		{
 			newHeightmap.push([]);
-			for (var y = 0; y < 2 * oldWidth - 1; y++)
+			for (var y = 0; y < 2 * oldWidth - 1; ++y)
 			{
 				if (x % 2 === 0 && y % 2 === 0) // Old tile
 					newHeightmap[x].push(initialHeightmap[x/2][y/2]);
@@ -412,9 +422,9 @@
 			}
 		}
 		// Diamond
-		for (var x = 0; x < 2 * oldWidth - 1; x++)
+		for (var x = 0; x < 2 * oldWidth - 1; ++x)
 		{
-			for (var y = 0; y < 2 * oldWidth - 1; y++)
+			for (var y = 0; y < 2 * oldWidth - 1; ++y)
 			{
 				if (newHeightmap[x][y] === undefined)
 				{
@@ -452,18 +462,15 @@
 	
 	// Cut initialHeightmap to fit target width
 	var shift = [floor((newHeightmap.length - heightmap.length) / 2), floor((newHeightmap[0].length - heightmap[0].length) / 2)];
-	for (var x = 0; x < heightmap.length; x++)
-		for (var y = 0; y < heightmap[0].length; y++)
+	for (var x = 0; x < heightmap.length; ++x)
+		for (var y = 0; y < heightmap[0].length; ++y)
 			heightmap[x][y] = newHeightmap[x][y];
 }
 
 
-////////////////
-//
-//  Terrain erosion functionality
-//
-////////////////
-
+/**
+ *  Terrain erosion functionality
+ */
 function decayErrodeHeightmap(strength, heightmap)
 {
 	strength = (strength || 0.9); // 0 to 1
@@ -474,9 +481,9 @@
 	var map = [[1, 0], [1, 1], [0, 1], [-1, 1], [-1, 0], [-1, -1], [0, -1], [1, -1]]; // smoother
 	var max_x = heightmap.length;
 	var max_y = heightmap[0].length;
-	for (var x = 0; x < max_x; x++)
-		for (var y = 0; y < max_y; y++)
-			for (var i = 0; i < map.length; i++)
+	for (var x = 0; x < max_x; ++x)
+		for (var y = 0; y < max_y; ++y)
+			for (var i = 0; i < map.length; ++i)
 				heightmap[x][y] += strength / map.length * (referenceHeightmap[(x + map[i][0] + max_x) % max_x][(y + map[i][1] + max_y) % max_y] - referenceHeightmap[x][y]); // Not entirely sure if scaling with map.length is perfect but tested values seam to indicate it is
 }
 
@@ -490,10 +497,10 @@
 	heightmap = (heightmap || g_Map.height);
 	
 	var heightmapWin = [];
-	for (var wx = 0; wx < 2 * dx + 1; wx++)
+	for (var wx = 0; wx < 2 * dx + 1; ++wx)
 	{
 		heightmapWin.push([]);
-		for (var wy = 0; wy < 2 * dy + 1; wy++)
+		for (var wy = 0; wy < 2 * dy + 1; ++wy)
 		{
 			var actualX = x - dx + wx;
 			var actualY = y - dy + wy;
@@ -503,9 +510,9 @@
 				heightmapWin[wx].push(targetHeight);
 		}
 	}
-	for (var wx = 0; wx < 2 * dx + 1; wx++)
+	for (var wx = 0; wx < 2 * dx + 1; ++wx)
 	{
-		for (var wy = 0; wy < 2 * dy + 1; wy++)
+		for (var wy = 0; wy < 2 * dy + 1; ++wy)
 		{
 			var actualX = x - dx + wx;
 			var actualY = y - dy + wy;
@@ -522,45 +529,53 @@
 }
 
 
-////////////////
-//
-//  Actually do stuff
-//
-////////////////
+/**
+ *  Actually do stuff
+ */
 
-////////////////
-// Set height limits and water level by map size
-////////////////
+/**
+ * Set height limits and water level by map size
+ */
 
-// Set target min and max height depending on map size to make average steepness about the same on all map sizes
+/**
+ * Set target min and max height depending on map size to make average steepness about the same on all map sizes
+ */
 var heightRange = {'min': MIN_HEIGHT * (g_Map.size + 512) / 8192, 'max': MAX_HEIGHT * (g_Map.size + 512) / 8192, 'avg': (MIN_HEIGHT * (g_Map.size + 512) +MAX_HEIGHT * (g_Map.size + 512))/16384};
 
-// Set average water coverage
+/**
+ * Set average water coverage
+ */
 var averageWaterCoverage = 1/5; // NOTE: Since erosion is not predictable actual water coverage might vary much with the same values
 var waterHeight = -MIN_HEIGHT + heightRange.min + averageWaterCoverage * (heightRange.max - heightRange.min);
 var waterHeightAdjusted = waterHeight + MIN_HEIGHT;
 setWaterHeight(waterHeight);
 
-////////////////
-// Generate base terrain
-////////////////
+/**
+ * Generate base terrain
+ */
 
-// Setting a 3x3 Grid as initial heightmap
+/**
+ * Setting a 3x3 Grid as initial heightmap
+ */
 var initialReliefmap = [[heightRange.max, heightRange.max, heightRange.max], [heightRange.max, heightRange.min, heightRange.max], [heightRange.max, heightRange.max, heightRange.max]];
 
 setBaseTerrainDiamondSquare(heightRange.min, heightRange.max, 0.5, initialReliefmap, g_Map.height);
-// Apply simple erosion
-for (var i = 0; i < 5; i++)
+/**
+ * Apply simple erosion
+ */
+for (var i = 0; i < 5; ++i)
 	decayErrodeHeightmap(0.5);
 rescaleHeightmap(heightRange.min, heightRange.max);
 
 RMS.SetProgress(50);
 
-//////////
-// Setup height limit
-//////////
+/**
+ * Setup height limit
+ */
 
-// Height presets
+/**
+ * Height presets
+ */
 var heighLimits = [
 	heightRange.min + 1/3 * (waterHeightAdjusted - heightRange.min), // 0 Deep water
 	heightRange.min + 2/3 * (waterHeightAdjusted - heightRange.min), // 1 Medium Water
@@ -574,15 +589,17 @@
 	waterHeightAdjusted + 7/8 * (heightRange.max - waterHeightAdjusted), // 9 Upper forest border
 	waterHeightAdjusted + (heightRange.max - waterHeightAdjusted)]; // 10 Hilltop
 
-//////////
-// Place start locations and apply terrain texture and decorative props
-//////////
+/**
+ * Place start locations and apply terrain texture and decorative props
+ */
 
-// Get start locations
+/**
+ * Get start locations
+ */
 var startLocations = getStartLocationsByHeightmap({'min': heighLimits[4], 'max': heighLimits[5]});
 var playerHeight = (heighLimits[4] + heighLimits[5]) / 2;
 
-for (var i=0; i < numPlayers; i++)
+for (var i=0; i < numPlayers; ++i)
 {
 	playerAngle[i] = (playerAngleStart + i*playerAngleAddAvrg + randFloat(0, playerAngleMaxOff))%(2*PI);
 	var x = round(mapCenterX + randFloat(minPlayerRadius, maxPlayerRadius)*cos(playerAngle[i]));
@@ -604,7 +621,7 @@
 	var distToSL = 15;
 	var resStartAngle = playerAngle[i] + PI;
 	var resAddAngle = 2*PI / startingResources.length;
-	for (var rIndex = 0; rIndex < startingResources.length; rIndex++)
+	for (var rIndex = 0; rIndex < startingResources.length; ++rIndex)
 	{
 		var angleOff = randFloat(-resAddAngle/2, resAddAngle/2);
 		var placeX = x + distToSL*cos(resStartAngle + rIndex*resAddAngle + angleOff);
@@ -614,13 +631,17 @@
 	}
 }
 
-// Add further stone and metal mines
+/**
+ * Add further stone and metal mines
+ */
 derivateEntitiesByHeight({'min': heighLimits[3], 'max': ((heighLimits[4]+heighLimits[3])/2)}, startLocations);
 derivateEntitiesByHeight({'min': ((heighLimits[5]+heighLimits[6])/2), 'max': heighLimits[7]}, startLocations);
 
 RMS.SetProgress(50);
 
-//place water & open terrain textures and assign TileClasses
+/**
+ * place water & open terrain textures and assign TileClasses
+ */
 log("Painting textures...");
 var placer = new HeightPlacer(heighLimits[2], (heighLimits[3]+heighLimits[2])/2);
 var painter = new LayeredPainter([terrainBase, terrainBaseBorder], [5]);
@@ -634,7 +655,9 @@
 
 RMS.SetProgress(60);
 
-// Place paths
+/**
+ * Place paths
+ */
 log("Placing paths...");
 var doublePaths = true;
 if (numPlayers > 4)
@@ -644,13 +667,13 @@
 	var maxI = numPlayers+1;
 else
 	var maxI = numPlayers;
-for (var i = 0; i < maxI; i++)
+for (var i = 0; i < maxI; ++i)
 {
 	if (doublePaths === true)
 		var minJ = 0;
 	else
 		var minJ = i+1;
-	for (var j = minJ; j < numPlayers+1; j++)
+	for (var j = minJ; j < numPlayers+1; ++j)
 	{
 		// Setup start and target coordinates
 		if (i < numPlayers)
@@ -700,7 +723,7 @@
 			}
 			if (getDistance(x, z, targetX, targetZ) < pathSucsessRadius)
 				targetReached = true;
-			tries++;
+			++tries;
 
 		}
 	}
@@ -708,7 +731,9 @@
 
 RMS.SetProgress(75);
 
-//create general decoration
+/**
+ *create general decoration
+ */
 log("Creating decoration...");
 createDecoration
 (
@@ -730,7 +755,9 @@
 
 RMS.SetProgress(80);
 
-//create fish
+/**
+ *create fish
+ */
 log("Growing fish...");
 createFood
 (
@@ -745,7 +772,9 @@
 
 RMS.SetProgress(85);
 
-// create reeds
+/**
+ * create reeds
+ */
 log("Planting reeds...");
 var types = [aReeds];	// some variation
 for (var i = 0; i < types.length; ++i)
@@ -759,16 +788,18 @@
 
 RMS.SetProgress(90);
 
-// place trees
+/**
+ * place trees
+ */
 log("Planting trees...");
-for (var x = 0; x < mapSize; x++)
+for (var x = 0; x < mapSize; ++x)
 {
-	for (var z = 0;z < mapSize;z++)
+	for (var z = 0; z < mapSize; ++z)
 	{
 		// Some variables
 		var radius = Math.pow(Math.pow(mapCenterX - x - 0.5, 2) + Math.pow(mapCenterZ - z - 0.5, 2), 1/2); // The 0.5 is a correction for the entities placed on the center of tiles
 		var minDistToSL = mapSize;
-		for (var i=0; i < numPlayers; i++)
+		for (var i=0; i < numPlayers; ++i)
 			minDistToSL = min(minDistToSL, getDistance(playerStartLocX[i], playerStartLocZ[i], x, z));
 		// Woods tile based
 		var tDensFactSL = max(min((minDistToSL - baseRadius) / baseRadius, 1), 0);
@@ -793,5 +824,7 @@
 
 RMS.SetProgress(100);
 
-// Export map data
+/**
+ * Export map data
+ */
 ExportMap();
